<commit_before>var DND_DATA = {
  versions: [{'0': 'Original'}
  ],

  species: {
    "0": {
      "": ["Accountant", "Human Resources Generalist", "IT Expert", "Personal Assistant", "Temp"]
    },
  },

  gen_text: [
    "Been There, Done That",
    "Been There, Done That Twice",
    "Nope",
    "Not That",
    "Re-Roll",
    "Re-Roll",
    "Try Again",
    "Try Again",
  ],

  adjective: [
    "Absent-minded",
    "Adventurous",
    "Agreeable",
    "Ambitious",
    "Amicable",
    "Anxious",
    "Apathetic",
    "Argumentative",
    "Assertive",
    "Attentive",
    "Bigoted",
    "Bitchy",
    "Blunt",
    "Boisterous",
    "Bossy",
    "Brave",
    "Broad-minded",
    "Callous",
    "Cautious",
    "Charming",
    "Cheerful",
    "Chipper",
    "Churchy",
    "Churlish",
    "Cold",
    "Compassionate",
    "Composed",
    "Conceited",
    "Condescending",
    "Confident",
    "Conscientious",
    "Considerate",
    "Cool-headed",
    "Courageous",
    "Crabby",
    "Crass",
    "Critical",
    "Cruel",
    "Cunning",
    "Curious",
    "Cynical",
    "Decisive",
    "Delightful",
    "Demure",
    "Dependable",
    "Depressed",
    "Determined",
    "Diligent",
    "Diplomatic",
    "Discerning",
    "Disruptive",
    "Dramatic",
    "Driven",
    "Drunken",
    "Dutiful",
    "Eager",
    "Easy-going",
    "Egotistical",
    "Elderly",
    "Emotional",
    "Enterprising",
    "Enthusiastic",
    "Excitable",
    "Faithful",
    "Fearless",
    "Flamboyant",
    "Flirtatious",
    "Frank",
    "Friendly",
    "Funny",
    "Fussy",
    "Generous",
    "Gentle",
    "Gloomy",
    "Grave",
    "Grouchy",
    "Gruff",
    "Guarded",
    "Hard-working",
    "Hateful",
    "Headstrong",
    "Helpful",
    "Hot-headed",
    "Hypercritical",
    "Impatient",
    "Impetuous",
    "Impulsive",
    "Inconsiderate",
    "Insensitive",
    "Intolerant",
    "Inventive",
    "Irritable",
    "Lazy",
    "Level-headed",
    "Loud",
    "Loyal",
    "Machiavellian",
    "Mean",
    "Melodramatic",
    "Methodical",
    "Meticulous",
    "Miserable",
    "Modest",
    "Moody",
    "Morose",
    "Motivated",
    "Naive",
    "Nosy",
    "Obnoxious",
    "Old-fashioned",
    "Outgoing",
    "Outspoken",
    "Overemotional",
    "Paranoid",
    "Passive-aggressive",
    "Peaceful",
    "Pensive",
    "Philosophical",
    "Plain-speaking",
    "Playful",
    "Plucky",
    "Pompous",
    "Positive",
    "Prejudiced",
    "Pretty chill",
    "Proud",
    "Quick-tempered",
    "Reliable",
    "Reluctant",
    "Resentful",
    "Resourceful",
    "Respectful",
    "Restless",
    "Romantic",
    "Sassy",
    "Selfish",
    "Sensitive",
    "Sentimental",
    "Short-tempered",
    "Snobby",
    "Sombre",
    "Sophisticated",
    "Soulless",
    "Spiteful",
    "Stern",
    "Stoic",
    "Surly",
    "Suspicious",
    "Sweet",
    "Tactless",
    "Talented",
    "Thoughtful",
    "Unbalanced",
    "Unpredictable",
    "Unstable",
    "Warm-hearted",
    "Wary",
    "Well-intentioned",
  ],

  race: [
    "Dragonborn",
    "Dwarf",
    "Elf",
    "Gnome",
    "Half-elf",
    "Half-orc",
    "Halfling",
    "Human",
    "Tiefling",
  ],

  dclass: [
    "Barbarian",
    "Bard",
    "Cleric",
    "Druid",
    "Fighter",
    "Monk",
    "Paladin",
    "Ranger",
    "Rogue",
    "Sorcerer",
    "Warlock",
    "Wizard",
  ],

  location: [
    "Alaska",
    "Amsterdam",
    "Atlanta",
    "Austin",
    "Baghdad",
    "Baltimore",
    "Barcelona",
    "Baton Rogue",
    "Beijing",
    "Berlin",
    "Bolivia",
    "Boston",
    "Boulder",
    "Budapest",
    "Calcutta",
    "Cairo",
    "Cardiff, Wales",
    "Chicago",
    "Cincinnati",
    "Columbus, Ohio",
    "Dallas",
    "Denver",
    "Des Moines",
    "Detroit",
    "Dubai",
    "El Paso",
    "Fargo, North Dakota",
    "Flagstaff",
    "Fresno",
    "Hawaii",
    "Hong Kong",
    "Houston",
    "Iceland",
    "Jackson, Mississippi",
    "Kansas City",
    "Kenya",
    "Lima, Peru",
    "London",
    "Los Angeles",
    "Los Vegas",
    "Lubbock, Texas",
    "Madrid",
    "Manilla, Philippines",
    "Memphis",
    "Mexico City",
    "Miami",
    "Milwaukee",
    "Minneapolis",
    "Moab, Utah",
    "Moldova",
    "Montreal, Canada",
    "Mumbai",
    "Nashville",
    "New Jersey",
    "New York City",
    "New Zealand",
    "North Dakota",
    "Oslo, Norway",
    "Paris",
    "Paris, Texas",
    "Philadelphia",
    "Portland",
    "Ramstein, Germany",
    "Reno",
    "Sacramento",
    "Salem, Oregon",
    "San Antonio",
    "San Diego",
    "San Francisco",
    "San Jose",
    "Seattle",
    "Seoul, Sourth Korea",
    "Sidney, Australia",
    "Singapore",
    "South Africa",
    "South Dakota",
    "São Paulo, Brazil",
    "Tokyo",
    "Toledo",
    "Tornto, Canada",
    "Tucson",
    "Tulsa",
    "Washington, D.C.",
    "rural Alabama",
    "rural Iowa",
    "rural Montana",
    "rural Nebraska",
    "rural Utah",
    "rural Vermont",
    "upstate New York",
  ],

  backstory: [
    "acts shallow but only to hide their insecurities",
    "acts younger than they are, but not in a good way",
    "always gets sloppy drunk at office parties",
    "always gives the bad news first",
    "always gives the good news first",
    "always invites people to Toastmasters",
    "always keeps their promises",
    "always looks bored",
    "always looks hungover",
    "always looks relaxed",
    "always looks tired",
    "always looks their best",
    "always shows up late",
    "always skips out early",
    "always needs to be the centre of attention",
    'always refers to inanimate objects as "she"',
    "always speaks in the third person",
    "always thinks outside the box",
    "always wanted to be an artist",
    "always wants to talk about their weekend",
    "argues with their spouse on the phone every day",
    "believes in an eye for an eye",
    'clearly partied hard when they were young and still thinks of themself as "cool" now',
    "clears their throat all day long",
    "collects those creepy porcelain dolls",
    "dresses inappropriately for work",
    "follows every sport on TV",
    "goes backpacking in the Summer",
    "goes to Burning Man every year",
    "has a dish of cheap candy on their desk",
    "has a dish of expensive chocolates on their desk",
    "has a dog instead of a child",
    "has a newborn and hasn't slept in weeks",
    "has a PhD in something useless",
    "has a terrible case or Resting Bitch Face, but is super nice",
    "has five cats at home",
    "has no chin",
    "has Resting Bitch Face",
    "has Seasonal Affective Disorder",
    "has the world's largest ugly sweater collection, but doesn't know it",
    "has two dogs and no kids",
    "has two drinks at lunch",
    "hasn't done any work in years",
    "is a huge drama queen",
    "is a jerk",
    "is a morning person",
    "is always complaining about how busy they are, but they aren't",
    "is always on the phone organization their kids soccer league",
    "is always relentlessly positive",
    "is counting the days until retirement",
    "is in a band",
    "is more of a night person",
    "is not cut out for office life",
    "is not using their college degree",
    "is really nice until you mention religion",
    "is super churchy",
    "is super nice and friendly; probably relaxed because they never do any work",
    "is technically polite, but in a really artifical fake way that no one trusts",
    "is terrible at conversation",
    "is the poster child for Peter Pan Syndrome",
    "is too good work here",
    "is too good work here and will probably leave soon",
    "is too nice",
    "is very concerned about appearances",
    "is very concerned about politics",
    "is WAY too friendly to management",
    "looks older than they are",
    "loves shopping and is deeply in debt",
    'married rich and is talking about "retiring" at 42',
    "married their highschool sweatheart",
    "mumbles incoherantly all the time",
    "never does any work and makes life harder for everyone around them",
    "never lets a conversation end when it should",
    "never shuts up about rock climbing",
    "only goes on vacation to Disneyland",
    "only talks to people of the opposite sex",
    "owns three rental houses and will probably retire early",
    "probably has Aspergers, but is really good at their job",
    "really wants to be management",
    "repeats everything you say",
    "smiles, but only with their mouth",
    "somehow married someone WAY more attractive than them",
    "should have retired years ago",
    "stills plays beer pong on the weekends",
    "thinks their child is a genius",
    "thinks their great at office politics, but really aren't",
    "used to be a body builder but has settled down and had kids",
    "used to be in good shape",
    "used to be in the military, so they come in early and work harder than everyone else",
    "uses big words to sound smart",
    "was clearly born into a rich family and doesn't need this job",
    "was really popular in high school, but is really jaded now",
    'was voted "most likely to become a serial killer" in highschool',
    "wears Daisy Dukes on Fridays",
    "won't shut up about their kids",
    "won't stop talking about their kids",
  ]
};

RPG_Char.init(DND_DATA);
<commit_msg>#75 content update<commit_after>var DND_DATA = {
  versions: [{'0': 'Original'}
  ],

  species: {
    "0": {
      "": ["Accountant", "Human Resources Generalist", "IT Expert", "Personal Assistant", "Temp"]
    },
  },

  gen_text: [
    "Been There, Done That",
    "Been There, Done That Twice",
    "Nope",
    "Not That",
    "Re-Roll",
    "Re-Roll",
    "Try Again",
    "Try Again",
  ],

  adjective: [
    "Absent-minded",
    "Adventurous",
    "Agreeable",
    "Ambitious",
    "Amicable",
    "Anxious",
    "Apathetic",
    "Argumentative",
    "Assertive",
    "Attentive",
    "Bigoted",
    "Bitchy",
    "Blunt",
    "Boisterous",
    "Bossy",
    "Brave",
    "Broad-minded",
    "Callous",
    "Cautious",
    "Charming",
    "Cheerful",
    "Chipper",
    "Churchy",
    "Churlish",
    "Cold",
    "Compassionate",
    "Composed",
    "Conceited",
    "Condescending",
    "Confident",
    "Conscientious",
    "Considerate",
    "Cool-headed",
    "Courageous",
    "Crabby",
    "Crass",
    "Critical",
    "Cruel",
    "Cunning",
    "Curious",
    "Cynical",
    "Decisive",
    "Delightful",
    "Demure",
    "Dependable",
    "Depressed",
    "Determined",
    "Diligent",
    "Diplomatic",
    "Discerning",
    "Disruptive",
    "Dramatic",
    "Driven",
    "Drunken",
    "Dutiful",
    "Eager",
    "Easy-going",
    "Egotistical",
    "Elderly",
    "Emotional",
    "Enterprising",
    "Enthusiastic",
    "Excitable",
    "Faithful",
    "Fearless",
    "Flamboyant",
    "Flirtatious",
    "Frank",
    "Friendly",
    "Funny",
    "Fussy",
    "Generous",
    "Gentle",
    "Gloomy",
    "Grave",
    "Grouchy",
    "Gruff",
    "Guarded",
    "Hard-working",
    "Hateful",
    "Headstrong",
    "Helpful",
    "Hot-headed",
    "Hypercritical",
    "Impatient",
    "Impetuous",
    "Impulsive",
    "Inconsiderate",
    "Insensitive",
    "Intolerant",
    "Inventive",
    "Irritable",
    "Lazy",
    "Level-headed",
    "Loud",
    "Loyal",
    "Machiavellian",
    "Mean",
    "Melodramatic",
    "Methodical",
    "Meticulous",
    "Miserable",
    "Modest",
    "Moody",
    "Morose",
    "Motivated",
    "Naive",
    "Nosy",
    "Obnoxious",
    "Old-fashioned",
    "Outgoing",
    "Outspoken",
    "Overemotional",
    "Paranoid",
    "Passive-aggressive",
    "Peaceful",
    "Pensive",
    "Philosophical",
    "Plain-speaking",
    "Playful",
    "Plucky",
    "Pompous",
    "Positive",
    "Prejudiced",
    "Pretty chill",
    "Proud",
    "Quick-tempered",
    "Reliable",
    "Reluctant",
    "Resentful",
    "Resourceful",
    "Respectful",
    "Restless",
    "Romantic",
    "Sassy",
    "Selfish",
    "Sensitive",
    "Sentimental",
    "Short-tempered",
    "Snobby",
    "Sombre",
    "Sophisticated",
    "Soulless",
    "Spiteful",
    "Stern",
    "Stoic",
    "Surly",
    "Suspicious",
    "Sweet",
    "Tactless",
    "Talented",
    "Thoughtful",
    "Unbalanced",
    "Unpredictable",
    "Unstable",
    "Warm-hearted",
    "Wary",
    "Well-intentioned",
  ],

  race: [
    "Dragonborn",
    "Dwarf",
    "Elf",
    "Gnome",
    "Half-elf",
    "Half-orc",
    "Halfling",
    "Human",
    "Tiefling",
  ],

  dclass: [
    "Barbarian",
    "Bard",
    "Cleric",
    "Druid",
    "Fighter",
    "Monk",
    "Paladin",
    "Ranger",
    "Rogue",
    "Sorcerer",
    "Warlock",
    "Wizard",
  ],

  location: [
    "Alaska",
    "Amsterdam",
    "Atlanta",
    "Austin",
    "Baghdad",
    "Baltimore",
    "Barcelona",
    "Baton Rogue",
    "Beijing",
    "Berlin",
    "Bolivia",
    "Boston",
    "Boulder",
    "Budapest",
    "Calcutta",
    "Cairo",
    "Cardiff, Wales",
    "Chicago",
    "Cincinnati",
    "Columbus, Ohio",
    "Dallas",
    "Denver",
    "Des Moines",
    "Detroit",
    "Dubai",
    "El Paso",
    "Fargo, North Dakota",
    "Flagstaff",
    "Fresno",
    "Hawaii",
    "Hong Kong",
    "Houston",
    "Iceland",
    "Jackson, Mississippi",
    "Kansas City",
    "Kenya",
    "Lima, Peru",
    "London",
    "Los Angeles",
    "Los Vegas",
    "Lubbock, Texas",
    "Madrid",
    "Manilla, Philippines",
    "Memphis",
    "Mexico City",
    "Miami",
    "Milwaukee",
    "Minneapolis",
    "Moab, Utah",
    "Moldova",
    "Montreal, Canada",
    "Mumbai",
    "Nashville",
    "New Jersey",
    "New York City",
    "New Zealand",
    "North Dakota",
    "Oslo, Norway",
    "Paris",
    "Paris, Texas",
    "Philadelphia",
    "Portland",
    "Ramstein, Germany",
    "Reno",
    "Sacramento",
    "Salem, Oregon",
    "San Antonio",
    "San Diego",
    "San Francisco",
    "San Jose",
    "Seattle",
    "Seoul, Sourth Korea",
    "Sidney, Australia",
    "Singapore",
    "South Africa",
    "South Dakota",
    "São Paulo, Brazil",
    "Tokyo",
    "Toledo",
    "Tornto, Canada",
    "Tucson",
    "Tulsa",
    "Washington, D.C.",
    "rural Alabama",
    "rural Iowa",
    "rural Montana",
    "rural Nebraska",
    "rural Utah",
    "rural Vermont",
    "upstate New York",
  ],

  backstory: [
    "acts shallow but only to hide their insecurities",
    "acts younger than they are, but not in a good way",
    "always gets sloppy drunk at office parties",
    "always gives the bad news first",
    "always gives the good news first",
    "always invites people to Toastmasters",
    "always keeps their promises",
    "always looks bored",
    "always looks hungover",
    "always looks relaxed",
    "always looks tired",
    "always looks their best",
    "always shows up late",
    "always skips out early",
    "always speaks very formally",
    "always needs to be the centre of attention",
    'always refers to inanimate objects as "she"',
    "always speaks in the third person",
    "always thinks outside the box",
    "always wanted to be an artist",
    "always wants to talk about their weekend",
    "argues with their spouse on the phone every day",
    "believes in an eye for an eye",
    'clearly partied hard when they were young and still thinks of themself as "cool" now',
    "clears their throat all day long",
    "collects those creepy porcelain dolls",
    "dresses inappropriately",
    "follows every sport on TV",
    "goes backpacking in the Summer",
    "goes to Burning Man every year",
    "has a dish of cheap candy on their desk",
    "has a dish of expensive chocolates on their desk",
    "has a dog instead of a child",
    "has a newborn and hasn't slept in weeks",
    "has a PhD in something useless",
    "has a terrible case or Resting Bitch Face, but is super nice",
    "has five cats at home",
    "has no chin",
    "has Resting Bitch Face",
    "has Seasonal Affective Disorder",
    "has the world's largest ugly sweater collection, but doesn't know it",
    "has two dogs and no kids",
    "has two drinks at lunch",
    "hasn't done any work in years",
    "is a huge drama queen",
    "is a jerk",
    "is a morning person",
    "is always complaining about how busy they are, but they aren't",
    "is always on the phone organization their kids soccer league",
    "is always relentlessly positive",
    "is counting the days until retirement",
    "is in a band",
    "is more of a night person",
    "is not cut out for office life",
    "is not using their college degree",
    "is really nice until you mention religion",
    "is really old-fashioned",
    "is super churchy",
    "is super nice and friendly; probably relaxed because they never do any work",
    "is technically polite, but in a really artifical fake way that no one trusts",
    "is terrible at conversation",
    "is the poster child for Peter Pan Syndrome",
    "is too good work here",
    "is too good work here and will probably leave soon",
    "is too nice",
    "is very concerned about appearances",
    "is very concerned about politics",
    "is WAY too friendly to management",
    "looks older than they are",
    "loves shopping and is deeply in debt",
    'married rich and is talking about "retiring" at 42',
    "married their highschool sweatheart",
    "mumbles incoherantly all the time",
    "never does any work and makes life harder for everyone around them",
    "never lets a conversation end when it should",
    "never shuts up about rock climbing",
    "only goes on vacation to Disneyland",
    "only talks to people of the opposite sex",
    "owns three rental houses and will probably retire early",
    "probably has Aspergers, but is really good at their job",
    "really wants to be management",
    "repeats everything you say",
    "smiles, but only with their mouth",
    "somehow married someone WAY more attractive than them",
    "should have retired years ago",
    "stills plays beer pong on the weekends",
    "thinks their child is a genius",
    "thinks their great at office politics, but really aren't",
    "used to be a body builder but has settled down and had kids",
    "used to be in good shape",
    "used to be in the military, so they come in early and work harder than everyone else",
    "uses big words to sound smart",
    "was clearly born into a rich family and doesn't need this job",
    "was really popular in high school, but is really jaded now",
    'was voted "most likely to become a serial killer" in highschool',
    "wears Daisy Dukes on Fridays",
    "won't shut up about their kids",
    "won't stop talking about their kids",
  ]
};

RPG_Char.init(DND_DATA);
<|endoftext|>


<commit_before>jQuery('.custom_upload_image_button').on('click',function() {
    var $this = jQuery(this);
    var formfield = $this.siblings('.custom_upload_image');
    var preview = $this.siblings('.custom_preview_image');

    tb_show('', 'media-upload.php?type=image&TB_iframe=true');
    window.send_to_editor = function(html) {
        var imgurl = jQuery(html).attr('src');
        var classes = jQuery(html).attr('class');

        var id = classes.replace(/(.*?)wp-image-/, '');

        formfield.val(id);
        preview.attr('src', imgurl);
        tb_remove();
    };

    return false;
});

jQuery('.custom_clear_image_button').on('click',function() {
    var $parent = jQuery(this).parent();
    var defaultImage = $parent.siblings('.custom_default_image').text();

    $parent.siblings('.custom_upload_image').val('');
    $parent.siblings('.custom_preview_image').attr('src', defaultImage);

    return false;
});

jQuery('#items_is_wine').on('change',function() {
    if(this.checked){
        jQuery('.normal-price').stop().hide();
        jQuery('.wine-price').stop().show();
    } else {
        jQuery('.normal-price').stop().show();
        jQuery('.wine-price').stop().hide();
    }
});

// Modified http://goessner.net/download/prj/jsonxml/
function json2xml(o,tab){
    var toXml = function(v,name,ind){
        var xml = '';
        if(v instanceof Array){
            for(var i = 0,n = v.length; i < n; i++)
                xml += ind + toXml(v[i],name,ind + '\t');
        }
        else if(typeof(v) == 'object'){
            var hasChild = false;
            xml += ind + '[' + name;
            for(var m in v){
                if(m.charAt(0) == '@')
                    xml += ' ' + m.substr(1) + '="' + v[m].toString() + '"';
                else
                    hasChild = true;
            }
            xml += hasChild ? ']' : '][/' + name + ']';
            if(hasChild){
                for(var m in v){
                    if(m == '#text')
                        xml += v[m];
                    else if(m == '#cdata')
                        xml += '<![CDATA[' + v[m] + ']]>';
                    else if(m.charAt(0) != '@')
                        xml += toXml(v[m],m,ind + '\t');
                }
                xml += (xml.charAt(xml.length - 1) == '\n' ? ind : '') + '[/' + name + ']';
            }
        }
        else {
            xml += ind + '[' + name + ']' + v.toString() + '[/' + name + ']';
        }
        return xml;
    },xml = '';
    for(var m in o)
        xml += toXml(o[m],m,'');
    return tab ? xml.replace(/\t/g,tab) : xml.replace(/\t/g,''); //xml.replace(/\t|\n/g,'')
}

// https://davidwalsh.name/convert-xml-json
function xmlToJson(xml) {
	var obj = {};
	if (xml.nodeType == 3) {
		obj = xml.nodeValue;
	}

	if (xml.hasChildNodes()) {
		for(var i = 0; i < xml.childNodes.length; i++) {
			var item = xml.childNodes.item(i);
			var nodeName = item.nodeName;

			if (typeof(obj[nodeName]) == 'undefined') {
				obj[nodeName] = xmlToJson(item);
			} else {
				if (typeof(obj[nodeName].push) == 'undefined') {
					var old = obj[nodeName];
					obj[nodeName] = [];
					obj[nodeName].push(old);
				}

				obj[nodeName].push(xmlToJson(item));
			}
		}
	}
	return obj;
}

(function($){
    var $editor = $('#menus_fixed_price');
    var $box = $('#menu_editor_box').find('.inside');
    var content = $editor.val();
    var tree = {};

    if(content){
        var xmlString = content.replace(/\[/g, '<').replace(/\]/g, '>');
        var xml = $.parseXML(xmlString);
        tree = xmlToJson(xml);
    } else {
        tree = {
            menu: {
                menu_title: {},
                menu_special: {
                    menu_category: []
                }
            }
        };
    }

    // Ensure that the menu_category level is an array even if there's only 1
    if(tree.menu && tree.menu.menu_special && tree.menu.menu_special.menu_category && !Array.isArray(tree.menu.menu_special.menu_category)){
        tree.menu.menu_special.menu_category = [tree.menu.menu_special.menu_category];
    }

    console.log(JSON.stringify(tree, true, 4));

    render();

    function makeTitle(name,className,type,category){
        category = typeof category === 'undefined' ? -1 : category;
        return '
' +
            '
' + name +
            '
Add ' + type + '

' +
            '
';
    }

    function makeInput(name,label,value,type,displayButtons,description){
        value = value || '';
        var html = '
';

        if(displayButtons){
            html += '
Up
	';
        } else if (displayButtons !== null) {
            html += '
Down
	';
        } else {
            html += '	';
        }

        html += '' + label + '	';
        html += '<input sie="150" type="text" id="ci-' + name + '" name="' + name + '" value="' + decodeURIComponent(value) + '" onkeyup="handleInputChange(event)"/>';

        if(description){
            html += '
' + description + '';
        }

        html += '	';
        if(displayButtons){
            html += '
Delete
	';
        }
        html += '
';
        return html;
    }

    function makeTextarea(name,label,value,displayButtons,description){
        value = value || '';
        var html = '
';

        if(displayButtons){
            html += '' +
                '
Up
' +
                '
Down
' +
            '	';
        } else {
            html += '	';
        }

        html += '' + label + '	';
        html += '<textarea cos="150" rows="7" id="ci-' + name + '" name="' + name + '" onkeyup="handleInputChange(event)">' +  decodeURIComponent(value) + '</textarea>';

        if(description){
            html += '
' + description + '';
        }

        html += '
';
        return html;
    }

    window.handleAddRow = function(event){
        var target = event.target;
        var type = target.getAttribute('data-type');
        var category = target.getAttribute('data-category');

        switch(type){
            case 'item':
                tree.menu.menu_special.menu_category[category].menu_items.menu_item.push({
                    menu_item_title: {},
                    menu_item_description: {}
                });
                break;
            case 'category':
                tree.menu.menu_special.menu_category.push({
                    menu_category_title: {},
                    menu_category_description: {},
                    menu_items: {
                        menu_item: []
                    }
                });
                break;
        }

        render();

        if(type === 'item'){
            //TODO: Fix this
            $('html, body').scrollTop($('.form-menu').find('tr').eq(category+2).find('tr').last().offset().top);
        } else {
            $('html, body').scrollTop($('.form-menu').find('tr').last().offset().top);
        }
    };

    window.handleInputChange = function(event){
        var target = event.target;
        var value = target.value;
        var id = target.id.replace('ci-','').split('-');
        var name = id[0];
        var category = typeof id[1] === 'undefined' ? null : id[1];
        var item = typeof id[2] === 'undefined' ? null : id[2];

        console.log('--------------')
        console.log('modified',name,category,item)
        console.log(value)
        console.log('--------------')

        switch(name){
            case 'menu_title':
                tree.menu.menu_title = {'#text': value};
                break;
            case 'menu_category_title':
            case 'menu_category_description':
                tree.menu.menu_special.menu_category[category][name] = {'#text': encodeURIComponent(value)};
                break;
            case 'menu_item_title':
            case 'menu_item_description':
                tree.menu.menu_special.menu_category[category].menu_items.menu_item[item][name] = {'#text': encodeURIComponent(value)};
                break;
        }

        console.log(JSON.stringify(tree, true, 4));
        console.log(json2xml(tree));
        $editor.html(json2xml(tree));
    };

    window.handleDeleteItem = function(event,type){
        console.log(type);
    };

    window.handleMoveItem = function(event,type){

    };

    function render(){
        var html = '

';
        html += makeTextarea('menu_title','Title',tree.menu.menu_title && tree.menu.menu_title['#text'] || '');
        html += makeTitle('Categories','categories','category');

        if(tree.menu.menu_special && tree.menu.menu_special.menu_category){
            tree.menu.menu_special.menu_category.forEach(function(menu_category,category_i){
                html += '

';
                html += makeInput('menu_category_title-' + category_i,'Category Name',menu_category.menu_category_title['#text'],'category',null);
                html += makeTextarea('menu_category_description-' + category_i,'Category Description',menu_category.menu_category_description['#text'],true);
                html += '

';

                if(menu_category.menu_items && menu_category.menu_items.menu_item){
                    // Ensure that the menu_item level is an array even if there's only 1
                    if(!Array.isArray(menu_category.menu_items.menu_item)){
                        menu_category.menu_items.menu_item = [menu_category.menu_items.menu_item];
                    }

                    html += makeTitle('Items','items','item',category_i);
                    menu_category.menu_items.menu_item.forEach(function(menu_item,item_i){
                        html += makeInput('menu_item_title-' + category_i + '-' + item_i,'Name',menu_item.menu_item_title['#text'],'item',true);
                        html += makeInput('menu_item_description-' + category_i + '-' + item_i,'Description',menu_item.menu_item_description['#text'],'item');
                    });
                }
                html += '

';
            });
        }

        html += '

';
        $box.html(html);
    }
})(jQuery);
<commit_msg>Fixed price menu support - Remove sizes for input & textarea, handled via CSS instead<commit_after>jQuery('.custom_upload_image_button').on('click',function() {
    var $this = jQuery(this);
    var formfield = $this.siblings('.custom_upload_image');
    var preview = $this.siblings('.custom_preview_image');

    tb_show('', 'media-upload.php?type=image&TB_iframe=true');
    window.send_to_editor = function(html) {
        var imgurl = jQuery(html).attr('src');
        var classes = jQuery(html).attr('class');

        var id = classes.replace(/(.*?)wp-image-/, '');

        formfield.val(id);
        preview.attr('src', imgurl);
        tb_remove();
    };

    return false;
});

jQuery('.custom_clear_image_button').on('click',function() {
    var $parent = jQuery(this).parent();
    var defaultImage = $parent.siblings('.custom_default_image').text();

    $parent.siblings('.custom_upload_image').val('');
    $parent.siblings('.custom_preview_image').attr('src', defaultImage);

    return false;
});

jQuery('#items_is_wine').on('change',function() {
    if(this.checked){
        jQuery('.normal-price').stop().hide();
        jQuery('.wine-price').stop().show();
    } else {
        jQuery('.normal-price').stop().show();
        jQuery('.wine-price').stop().hide();
    }
});

// Modified http://goessner.net/download/prj/jsonxml/
function json2xml(o,tab){
    var toXml = function(v,name,ind){
        var xml = '';
        if(v instanceof Array){
            for(var i = 0,n = v.length; i < n; i++)
                xml += ind + toXml(v[i],name,ind + '\t');
        }
        else if(typeof(v) == 'object'){
            var hasChild = false;
            xml += ind + '[' + name;
            for(var m in v){
                if(m.charAt(0) == '@')
                    xml += ' ' + m.substr(1) + '="' + v[m].toString() + '"';
                else
                    hasChild = true;
            }
            xml += hasChild ? ']' : '][/' + name + ']';
            if(hasChild){
                for(var m in v){
                    if(m == '#text')
                        xml += v[m];
                    else if(m == '#cdata')
                        xml += '<![CDATA[' + v[m] + ']]>';
                    else if(m.charAt(0) != '@')
                        xml += toXml(v[m],m,ind + '\t');
                }
                xml += (xml.charAt(xml.length - 1) == '\n' ? ind : '') + '[/' + name + ']';
            }
        }
        else {
            xml += ind + '[' + name + ']' + v.toString() + '[/' + name + ']';
        }
        return xml;
    },xml = '';
    for(var m in o)
        xml += toXml(o[m],m,'');
    return tab ? xml.replace(/\t/g,tab) : xml.replace(/\t/g,''); //xml.replace(/\t|\n/g,'')
}

// https://davidwalsh.name/convert-xml-json
function xmlToJson(xml) {
	var obj = {};
	if (xml.nodeType == 3) {
		obj = xml.nodeValue;
	}

	if (xml.hasChildNodes()) {
		for(var i = 0; i < xml.childNodes.length; i++) {
			var item = xml.childNodes.item(i);
			var nodeName = item.nodeName;

			if (typeof(obj[nodeName]) == 'undefined') {
				obj[nodeName] = xmlToJson(item);
			} else {
				if (typeof(obj[nodeName].push) == 'undefined') {
					var old = obj[nodeName];
					obj[nodeName] = [];
					obj[nodeName].push(old);
				}

				obj[nodeName].push(xmlToJson(item));
			}
		}
	}
	return obj;
}

(function($){
    var $editor = $('#menus_fixed_price');
    var $box = $('#menu_editor_box').find('.inside');
    var content = $editor.val();
    var tree = {};

    if(content){
        var xmlString = content.replace(/\[/g, '<').replace(/\]/g, '>');
        var xml = $.parseXML(xmlString);
        tree = xmlToJson(xml);
    } else {
        tree = {
            menu: {
                menu_title: {},
                menu_special: {
                    menu_category: []
                }
            }
        };
    }

    // Ensure that the menu_category level is an array even if there's only 1
    if(tree.menu && tree.menu.menu_special && tree.menu.menu_special.menu_category && !Array.isArray(tree.menu.menu_special.menu_category)){
        tree.menu.menu_special.menu_category = [tree.menu.menu_special.menu_category];
    }

    console.log(JSON.stringify(tree, true, 4));

    render();

    function makeTitle(name,className,type,category){
        category = typeof category === 'undefined' ? -1 : category;
        return '
' +
            '
' + name +
            '
Add ' + type + '

' +
            '
';
    }

    function makeInput(name,label,value,type,displayButtons,description){
        value = value || '';
        var html = '
';

        if(displayButtons){
            html += '
Up
	';
        } else if (displayButtons !== null) {
            html += '
Down
	';
        } else {
            html += '	';
        }

        html += '' + label + '	';
        html += '<input type="text" id="ci-' + name + '" name="' + name + '" value="' + decodeURIComponent(value) + '" onkeyup="handleInputChange(event)"/>';

        if(description){
            html += '
' + description + '';
        }

        html += '	';
        if(displayButtons){
            html += '
Delete
	';
        }
        html += '
';
        return html;
    }

    function makeTextarea(name,label,value,displayButtons,description){
        value = value || '';
        var html = '
';

        if(displayButtons){
            html += '' +
                '
Up
' +
                '
Down
' +
            '	';
        } else {
            html += '	';
        }

        html += '' + label + '	';
        html += '<textarea rows="7" id="ci-' + name + '" name="' + name + '" onkeyup="handleInputChange(event)">' +  decodeURIComponent(value) + '</textarea>';

        if(description){
            html += '
' + description + '';
        }

        html += '
';
        return html;
    }

    window.handleAddRow = function(event){
        var target = event.target;
        var type = target.getAttribute('data-type');
        var category = target.getAttribute('data-category');

        switch(type){
            case 'item':
                tree.menu.menu_special.menu_category[category].menu_items.menu_item.push({
                    menu_item_title: {},
                    menu_item_description: {}
                });
                break;
            case 'category':
                tree.menu.menu_special.menu_category.push({
                    menu_category_title: {},
                    menu_category_description: {},
                    menu_items: {
                        menu_item: []
                    }
                });
                break;
        }

        render();

        if(type === 'item'){
            //TODO: Fix this
            $('html, body').scrollTop($('.form-menu').find('tr').eq(category+2).find('tr').last().offset().top);
        } else {
            $('html, body').scrollTop($('.form-menu').find('tr').last().offset().top);
        }
    };

    window.handleInputChange = function(event){
        var target = event.target;
        var value = target.value;
        var id = target.id.replace('ci-','').split('-');
        var name = id[0];
        var category = typeof id[1] === 'undefined' ? null : id[1];
        var item = typeof id[2] === 'undefined' ? null : id[2];

        console.log('--------------')
        console.log('modified',name,category,item)
        console.log(value)
        console.log('--------------')

        switch(name){
            case 'menu_title':
                tree.menu.menu_title = {'#text': value};
                break;
            case 'menu_category_title':
            case 'menu_category_description':
                tree.menu.menu_special.menu_category[category][name] = {'#text': encodeURIComponent(value)};
                break;
            case 'menu_item_title':
            case 'menu_item_description':
                tree.menu.menu_special.menu_category[category].menu_items.menu_item[item][name] = {'#text': encodeURIComponent(value)};
                break;
        }

        console.log(JSON.stringify(tree, true, 4));
        console.log(json2xml(tree));
        $editor.html(json2xml(tree));
    };

    window.handleDeleteItem = function(event,type){
        console.log(type);
    };

    window.handleMoveItem = function(event,type){

    };

    function render(){
        var html = '

';
        html += makeTextarea('menu_title','Title',tree.menu.menu_title && tree.menu.menu_title['#text'] || '');
        html += makeTitle('Categories','categories','category');

        if(tree.menu.menu_special && tree.menu.menu_special.menu_category){
            tree.menu.menu_special.menu_category.forEach(function(menu_category,category_i){
                html += '

';
                html += makeInput('menu_category_title-' + category_i,'Category Name',menu_category.menu_category_title['#text'],'category',null);
                html += makeTextarea('menu_category_description-' + category_i,'Category Description',menu_category.menu_category_description['#text'],true);
                html += '

';

                if(menu_category.menu_items && menu_category.menu_items.menu_item){
                    // Ensure that the menu_item level is an array even if there's only 1
                    if(!Array.isArray(menu_category.menu_items.menu_item)){
                        menu_category.menu_items.menu_item = [menu_category.menu_items.menu_item];
                    }

                    html += makeTitle('Items','items','item',category_i);
                    menu_category.menu_items.menu_item.forEach(function(menu_item,item_i){
                        html += makeInput('menu_item_title-' + category_i + '-' + item_i,'Name',menu_item.menu_item_title['#text'],'item',true);
                        html += makeInput('menu_item_description-' + category_i + '-' + item_i,'Description',menu_item.menu_item_description['#text'],'item');
                    });
                }
                html += '

';
            });
        }

        html += '

';
        $box.html(html);
    }
})(jQuery);
<|endoftext|>


<commit_before>/* @flow */

export type Roll = number | {
  die: number,
  result: number,
  mod?: 'keep' | 'drop'
}

export type MessageResult = Array<Roll>;

/* Message type */
export type Message = {
  key: string,
  from: string,
  text: string,
  result: ?MessageResult,
  timestamp: number
}

/* Messages sent/received by Firebase */
export type FirebaseMessage = {
  name: string,
  result: ?MessageResult,
  text: string,
  timestamp: number
}

export type SessionMeta = {
  name: string
}

export type SessionInfo = {
  sessionId: string,
  meta?: SessionMeta
}

export type SessionList = {
  [key: string]: SessionInfo
}

export type Theme = 'light' | 'dark'

export type Tab = 'Session' | 'Character' | 'Sessions'
<commit_msg>Remove extra semi.<commit_after>/* @flow */

export type Roll = number | {
  die: number,
  result: number,
  mod?: 'keep' | 'drop'
}

export type MessageResult = Array<Roll>

/* Message type */
export type Message = {
  key: string,
  from: string,
  text: string,
  result: ?MessageResult,
  timestamp: number
}

/* Messages sent/received by Firebase */
export type FirebaseMessage = {
  name: string,
  result: ?MessageResult,
  text: string,
  timestamp: number
}

export type SessionMeta = {
  name: string
}

export type SessionInfo = {
  sessionId: string,
  meta?: SessionMeta
}

export type SessionList = {
  [key: string]: SessionInfo
}

export type Theme = 'light' | 'dark'

export type Tab = 'Session' | 'Character' | 'Sessions'
<|endoftext|>


<commit_before>
"use strict";

export default ['$route', ($route) => {

    function found(element, path, args) {
        for (let a in args) {
            path = path.replace(':' + a, args[a]);
        }
        element.attr('href', '#' + path.replace(/^#/, ''));
    };

    return {
        restrict: 'A',
        link: (scope, element, attrs) => {
            if (!(attrs.moPath)) {
                return;
            }
            let path = scope.$eval(attrs.moPath);
            if (!path) {
                return;
            }
            let args = attrs['arguments'] ? scope.$eval(attrs['arguments']) : {};
            args.language = args.language || $route.current.params.language;
            for (let _path in $route.routes) {
                let _pC = ($route.routes[_path].controller || '') + '';
                if (_pC.toLowerCase() == path.toLowerCase()) {
                    return found(element, _path, args);
                }
            }
            return found(element, path, args);
        }
    };
}];

<commit_msg>handle default language better and in a testable way<commit_after>
"use strict";

export default ['$route', $route => {

    function found(element, path, args) {
        for (let a in args) {
            path = path.replace(':' + a, args[a]);
        }
        element.attr('href', '#' + path.replace(/^#/, ''));
    };

    return {
        restrict: 'A',
        link: (scope, element, attrs) => {
            if (!(attrs.moPath)) {
                return;
            }
            let path = scope.$eval(attrs.moPath);
            if (!path) {
                return;
            }
            let args = attrs['arguments'] ? scope.$eval(attrs['arguments']) : {};
            if ($route.current && $route.current.params && $route.current.params.language) {
                args.language = args.language || $route.current.params.language;
            } else {
                args.language = args.language || 'en';
            }
            for (let _path in $route.routes) {
                let _pC = ($route.routes[_path].controller || '') + '';
                if (_pC.toLowerCase() == path.toLowerCase()) {
                    return found(element, _path, args);
                }
            }
            return found(element, path, args);
        }
    };
}];

<|endoftext|>


<commit_before>// Copyright 2015 The Oppia Authors. 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.

/**
 * @fileoverview Primary controller for the collection editor page.
 *
 * @author mgowano@google.com (Abraham Mgowano)
 */

// TODO(bhenning): These constants should be provided by the backend.
oppia.constant(
  'COLLECTION_DATA_URL', '/collection_handler/data/<collection_id>');
oppia.constant(
  'WRITABLE_COLLECTION_DATA_URL', '/collection_editor/data/<collection_id>');

oppia.controller('CollectionEditor', ['$scope', 'CollectionBackendApiService',
  'WritableCollectionBackendApiService', 'CollectionUpdateService',
  'warningsData', function(
    $scope, CollectionBackendApiService, WritableCollectionBackendApiService,
    CollectionUpdateService, warningsData) {

  $scope.collection = null;
  $scope.collectionId = GLOBALS.collectionId;
  $scope.collectionSkills = null;

  // Get the id of the collection to be loaded
  var pathnameArray = window.location.pathname.split('/');
  for (var i = 0; i < pathnameArray.length; i++) {
    if (pathnameArray[i] === 'create') {
      $scope.collectionId = pathnameArray[i + 1];
      break;
    }
  }

  // Load the collection to be edited.
  CollectionBackendApiService.loadCollection($scope.collectionId).then(
    function(collection) {
      $scope.collection = collection;
      $scope.collectionSkills = collection.skills;
    }, function(error) {
      // TODO(mgowano): Handle not being able to load the collection.
      warningsData.addWarning(
        error || 'There was an error loading the collection.');
  });

  var _arrayContainsCaseInsensitive = function(array, element) {
    var lowerElement = element.toLowerCase();
    for (var i = 0; i < array.length; i++) {
      if (array[i].toLowerCase() === lowerElement) {
        return true;
      }
    }
    return false;
  };

  var _getCollectionNodeForExplorationId = function(explorationId) {
    for (var i = 0; i < $scope.collection.nodes.length; i++) {
      var collectionNode = $scope.collection.nodes[i];
      if (collectionNode.exploration_id == explorationId) {
        return collectionNode;
      }
    }
    return null;
  };

  // Stores a pending list of changes.
  $scope.changeList = [];

  $scope.addChange = function(change) {
    $scope.changeList.push(change);
  };

  // TODO(mgowano): Handle a case where adding a pre-requisite skill
  // will result into having all exploration requiring pre-requisite
  // skills. At the moment this is only handled when a change is committed
  // to the backend.
  $scope.addPrerequisiteSkill = function(skillName, expId) {
    if (skillName && expId) {
      var collectionNode = _getCollectionNodeForExplorationId(expId);
      var prerequisiteSkills = collectionNode.prerequisite_skills;
      if (!_arrayContainsCaseInsensitive(prerequisiteSkills, skillName)) {
        prerequisiteSkills.push(skillName);
        return true;
      }
    }
    return false;
  };

  // TODO(mgowano): Handle cases where deleting a pre-requisite skill results
  // to unreachable explorations.
  $scope.deletePrerequisiteSkill = function(skillIdx, expId) {
    if (skillIdx) {
      var collectionNode = _getCollectionNodeForExplorationId(expId);
      collectionNode.prerequisite_skills.splice(skillIdx, 1);
      return true;
    }
    return false;
  };

  $scope.addAcquiredSkill = function(skillName, expId) {
    if (expId && skillName) {
      var collectionNode = _getCollectionNodeForExplorationId(expId);
      var acquiredSkills = collectionNode.acquired_skills;
      if (!_arrayContainsCaseInsensitive(acquiredSkills, skillName)) {
        acquiredSkills.push(skillName);
        return true;
      }
    }
    return false;
  };

  // TODO(mgowano): Handle cases where deleting an acquired skill results
  // to unreachable explorations.
  $scope.deleteAcquiredSkill = function(skillIdx, expId) {
    if (expId) {
      var collectionNode = _getCollectionNodeForExplorationId(expId);
      collectionNode.acquired_skills.splice(skillIdx, 1);
      return true;
    }
    return false;
  };

  // TODO(mgowano): Handle a case where deleting an exploration will
  // result into unreachable exploration. At the moment this is only
  // handled when a change is committed to the backend.
  $scope.deleteCollectionNode = function(expId) {
    if (expId) {
      for (var i = 0; i < $scope.collection.nodes.length; i++) {
        var collectionNode = $scope.collection.nodes[i];
        if (collectionNode.exploration_id == expId) {
          $scope.collection.nodes.splice(i, 1);
          return true;
        }
      }
    }
    return false;
  };

  // TODO(mgowano): Set all values for the 'exploration' key in newNode
  $scope.addCollectionNode = function(expId) {
    if (expId) {
      if (!_getCollectionNodeForExplorationId(expId)) {
        var newNode = {
          exploration_id: expId,
          acquired_skills: [],
          prerequisite_skills: [],
          exploration: {
            id: expId
          }
        }
        $scope.collection.nodes.push(newNode);
        return true;
      } else {
        warningsData.addWarning(
          'Exploration with id ' + expId + ' is already added');
      }
    }
    return false;
  };

  $scope.setCollectionTitle = function(newTitle) {
    if (newTitle) {
      $scope.collection.title = newTitle;
      return true;
    }
    return false;
  };

  $scope.setCollectionObjective = function(newObjective) {
    if (newObjective) {
      $scope.collection.objective = newObjective;
      return true;
    }
    return false;
  };

  $scope.setCollectionCategory = function(newCategory) {
    if (newCategory) {
      $scope.collection.category = newCategory;
      return true;
    }
    return false;
  };

  // An explicit save is needed to push all changes to the backend at once
  // because some likely working states of the collection will cause validation
  // errors when trying to incrementally save them.
  $scope.saveCollection = function(commitMessage) {
    WritableCollectionBackendApiService.updateCollection(
      $scope.collection.id, $scope.collection.version, commitMessage,
      $scope.changeList).then(function(collection) {
        $scope.collection = collection;
        $scope.changeList = [];
      }, function(error) {
        warningsData.addWarning(
          error || 'There was an error updating the collection.');
      });
  };
}]);
<commit_msg>Fixed a bug with removing prerequisite skills and ensured collections cannot be saved if they have no pending change list (to avoid a backend error).<commit_after>// Copyright 2015 The Oppia Authors. 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.

/**
 * @fileoverview Primary controller for the collection editor page.
 *
 * @author mgowano@google.com (Abraham Mgowano)
 */

// TODO(bhenning): These constants should be provided by the backend.
oppia.constant(
  'COLLECTION_DATA_URL', '/collection_handler/data/<collection_id>');
oppia.constant(
  'WRITABLE_COLLECTION_DATA_URL', '/collection_editor/data/<collection_id>');

oppia.controller('CollectionEditor', ['$scope', 'CollectionBackendApiService',
  'WritableCollectionBackendApiService', 'CollectionUpdateService',
  'warningsData', function(
    $scope, CollectionBackendApiService, WritableCollectionBackendApiService,
    CollectionUpdateService, warningsData) {

  $scope.collection = null;
  $scope.collectionId = GLOBALS.collectionId;
  $scope.collectionSkills = null;

  // Get the id of the collection to be loaded
  var pathnameArray = window.location.pathname.split('/');
  for (var i = 0; i < pathnameArray.length; i++) {
    if (pathnameArray[i] === 'create') {
      $scope.collectionId = pathnameArray[i + 1];
      break;
    }
  }

  // Load the collection to be edited.
  CollectionBackendApiService.loadCollection($scope.collectionId).then(
    function(collection) {
      $scope.collection = collection;
      $scope.collectionSkills = collection.skills;
    }, function(error) {
      // TODO(mgowano): Handle not being able to load the collection.
      warningsData.addWarning(
        error || 'There was an error loading the collection.');
  });

  var _arrayContainsCaseInsensitive = function(array, element) {
    var lowerElement = element.toLowerCase();
    for (var i = 0; i < array.length; i++) {
      if (array[i].toLowerCase() === lowerElement) {
        return true;
      }
    }
    return false;
  };

  var _getCollectionNodeForExplorationId = function(explorationId) {
    for (var i = 0; i < $scope.collection.nodes.length; i++) {
      var collectionNode = $scope.collection.nodes[i];
      if (collectionNode.exploration_id == explorationId) {
        return collectionNode;
      }
    }
    return null;
  };

  // Stores a pending list of changes.
  $scope.changeList = [];

  $scope.addChange = function(change) {
    $scope.changeList.push(change);
  };

  // TODO(mgowano): Handle a case where adding a pre-requisite skill
  // will result into having all exploration requiring pre-requisite
  // skills. At the moment this is only handled when a change is committed
  // to the backend.
  $scope.addPrerequisiteSkill = function(skillName, expId) {
    if (skillName && expId) {
      var collectionNode = _getCollectionNodeForExplorationId(expId);
      var prerequisiteSkills = collectionNode.prerequisite_skills;
      if (!_arrayContainsCaseInsensitive(prerequisiteSkills, skillName)) {
        prerequisiteSkills.push(skillName);
        return true;
      }
    }
    return false;
  };

  // TODO(mgowano): Handle cases where deleting a pre-requisite skill results
  // to unreachable explorations.
  $scope.deletePrerequisiteSkill = function(skillIdx, expId) {
    if (expId) {
      var collectionNode = _getCollectionNodeForExplorationId(expId);
      collectionNode.prerequisite_skills.splice(skillIdx, 1);
      return true;
    }
    return false;
  };

  $scope.addAcquiredSkill = function(skillName, expId) {
    if (skillName && expId) {
      var collectionNode = _getCollectionNodeForExplorationId(expId);
      var acquiredSkills = collectionNode.acquired_skills;
      if (!_arrayContainsCaseInsensitive(acquiredSkills, skillName)) {
        acquiredSkills.push(skillName);
        return true;
      }
    }
    return false;
  };

  // TODO(mgowano): Handle cases where deleting an acquired skill results
  // to unreachable explorations.
  $scope.deleteAcquiredSkill = function(skillIdx, expId) {
    if (expId) {
      var collectionNode = _getCollectionNodeForExplorationId(expId);
      collectionNode.acquired_skills.splice(skillIdx, 1);
      return true;
    }
    return false;
  };

  // TODO(mgowano): Handle a case where deleting an exploration will
  // result into unreachable exploration. At the moment this is only
  // handled when a change is committed to the backend.
  $scope.deleteCollectionNode = function(expId) {
    if (expId) {
      for (var i = 0; i < $scope.collection.nodes.length; i++) {
        var collectionNode = $scope.collection.nodes[i];
        if (collectionNode.exploration_id == expId) {
          $scope.collection.nodes.splice(i, 1);
          return true;
        }
      }
    }
    return false;
  };

  // TODO(mgowano): Set all values for the 'exploration' key in newNode
  $scope.addCollectionNode = function(expId) {
    if (expId) {
      if (!_getCollectionNodeForExplorationId(expId)) {
        var newNode = {
          exploration_id: expId,
          acquired_skills: [],
          prerequisite_skills: [],
          exploration: {
            id: expId
          }
        }
        $scope.collection.nodes.push(newNode);
        return true;
      } else {
        warningsData.addWarning(
          'Exploration with id ' + expId + ' is already added');
      }
    }
    return false;
  };

  $scope.setCollectionTitle = function(newTitle) {
    if (newTitle) {
      $scope.collection.title = newTitle;
      return true;
    }
    return false;
  };

  $scope.setCollectionObjective = function(newObjective) {
    if (newObjective) {
      $scope.collection.objective = newObjective;
      return true;
    }
    return false;
  };

  $scope.setCollectionCategory = function(newCategory) {
    if (newCategory) {
      $scope.collection.category = newCategory;
      return true;
    }
    return false;
  };

  // An explicit save is needed to push all changes to the backend at once
  // because some likely working states of the collection will cause validation
  // errors when trying to incrementally save them.
  $scope.saveCollection = function(commitMessage) {
    // Don't attempt to save the collection if there are no changes pending.
    if ($scope.changeList.length == 0) {
      return;
    }
    WritableCollectionBackendApiService.updateCollection(
      $scope.collection.id, $scope.collection.version, commitMessage,
      $scope.changeList).then(function(collection) {
        $scope.collection = collection;
        $scope.changeList = [];
      }, function(error) {
        warningsData.addWarning(
          error || 'There was an error updating the collection.');
      });
  };
}]);
<|endoftext|>


<commit_before>import firebase from 'firebase';
import EventEmitter from 'events';
import { config } from '../config';

/**
 * extend EventEmitter so user of NoteRepository can react to
 * our custom events (ex: noteRepository.on('added'))
 */
class NoteRepository extends EventEmitter {
  constructor() {
    super();

    // Initialize Firebase
    firebase.initializeApp(config);

    // Firebase database reference to notes
    this.ref = firebase.database().ref('notes');
    this.attachFirebaseListeners();
  }

  // creates a note
  create({ title = '', content = '', }, onComplete) {
    this.ref.push({ title, content }, onComplete);
  }

  // updates a note
  update({ key, title = '', content = '' }, onComplete) {
    this.ref.child(key).update({ title, content }, onComplete);
  }

  // removes a note
  remove({ id: key }, onComplete) {
    this.ref.child(key).remove(onComplete);
  }

  // Finds the index of the note inside the 'notes' array by looking for its key
  findIndex(notes, key) {
    return notes.findIndex(note => note.key === key);
  }

  // Finds the note inside the 'notes' array by searching for its key
  find(notes, key) {
    return notes.find(note => note.key === key);
  }

  // process snapshot data and add unique Firebase key to each note
  snapshotToNote(snapshot) {
    const { key } = snapshot;
    const note = { ...snapshot.val(), key };
    return note;
  }

  /**
   * The event listeners process the data passed through from
   * the Firebase DataSnapshots and then propagate the events outward
   */
  onAdded(snapshot) {
    const note = this.snapshotToNote(snapshot);
    this.emit('added', note);
  }

  onRemoved(oldSnapshot) {
    const note = this.snapshotToNote(oldSnapshot);
    this.emit('removed', note);
  }

  onChanged(snapshot) {
    const note = this.snapshotToNote(snapshot);
    this.emit('changed', note);
  }

  // attach event listeners to Firebase
  attachFirebaseListeners() {
    this.ref.on('child_added', this.onAdded, this);
    this.ref.on('child_removed', this.onRemoved, this);
    this.ref.on('child_changed', this.onChanged, this);
  }
}

export default new NoteRepository();
<commit_msg>Add `detachFirebaseListeners` method<commit_after>import firebase from 'firebase';
import EventEmitter from 'events';
import { config } from '../config';

/**
 * extend EventEmitter so user of NoteRepository can react to
 * our custom events (ex: noteRepository.on('added'))
 */
class NoteRepository extends EventEmitter {
  constructor() {
    super();

    // Initialize Firebase
    firebase.initializeApp(config);

    // Firebase database reference to notes
    this.ref = firebase.database().ref('notes');
    this.attachFirebaseListeners();
  }

  // creates a note
  create({ title = '', content = '', }, onComplete) {
    this.ref.push({ title, content }, onComplete);
  }

  // updates a note
  update({ key, title = '', content = '' }, onComplete) {
    this.ref.child(key).update({ title, content }, onComplete);
  }

  // removes a note
  remove({ id: key }, onComplete) {
    this.ref.child(key).remove(onComplete);
  }

  // Finds the index of the note inside the 'notes' array by looking for its key
  findIndex(notes, key) {
    return notes.findIndex(note => note.key === key);
  }

  // Finds the note inside the 'notes' array by searching for its key
  find(notes, key) {
    return notes.find(note => note.key === key);
  }

  // process snapshot data and add unique Firebase key to each note
  snapshotToNote(snapshot) {
    const { key } = snapshot;
    const note = { ...snapshot.val(), key };
    return note;
  }

  /**
   * The event listeners process the data passed through from
   * the Firebase DataSnapshots and then propagate the events outward
   */
  onAdded(snapshot) {
    const note = this.snapshotToNote(snapshot);
    this.emit('added', note);
  }

  onRemoved(oldSnapshot) {
    const note = this.snapshotToNote(oldSnapshot);
    this.emit('removed', note);
  }

  onChanged(snapshot) {
    const note = this.snapshotToNote(snapshot);
    this.emit('changed', note);
  }

  // attach event listeners to Firebase
  attachFirebaseListeners() {
    this.ref.on('child_added', this.onAdded, this);
    this.ref.on('child_removed', this.onRemoved, this);
    this.ref.on('child_changed', this.onChanged, this);
  }

  // detach listeners from Firebase
  detachFirebaseListeners() {
    this.ref.off('child_added', this.onAdded, this);
    this.ref.off('child_removed', this.onRemoved, this);
    this.ref.off('child_changed', this.onChanged, this);
  }
}

export default new NoteRepository();
<|endoftext|>


<commit_before>function invalidInput(element, fn) {
  my_addClass(element, 'invalid');
  element.onkeypress = function() {
    if (fn(element.value)) {
      my_removeClass(this, 'invalid');
      my_addClass(this, 'valid');
    }
  }
}

function emailFormHandler() {
  var sendEmailBtn = document.getElementById('squatch-send-email');
  var firstName = document.getElementById('squatch-user-firstname');
  var lastName = document.getElementById('squatch-user-lastname');
  var emailInput = document.getElementById('squatch-user-email');

  handleClicks(sendEmailBtn, function() {
    var noErrors = true;

    if (firstName && firstName.value.length < 1) {
      noErrors = false;
      invalidInput(firstName, function(e) { return e.length < 1; });
    }

    if (lastName && lastName.value.length < 1) {
      noErrors = false;
      invalidInput(lastName, function(e) { return e.length < 1; });
    }

    if (!isValidEmail(emailInput.value)) {
      noErrors = false;
      invalidInput(emailInput, function(e) { return isValidEmail(e); });
    }

    if (noErrors) {
      var paramsObj = {};

      if (firstName) {
        my_removeClass(firstName, 'invalid');
        paramsObj.firstName = firstName.value;
      }

      if (lastName) {
         my_removeClass(lastName, 'invalid');
         paramsObj.lastName = lastName.value;
      }

      if (emailInput) {
        my_removeClass(emailInput, 'invalid');
        paramsObj.email = emailInput.value;
      }

      if (window.frameElement && window.frameElement.squatchJsApi) {
        var widget = window.frameElement.squatchJsApi;

        if (window.parent.squatch && window.parent.squatch.widgets().eventBus) {
          window.parent.squatch.widgets().eventBus.dispatch('submit_email', this, widget, paramsObj);
        } else {
          window.frameElement.squatchJsApi.reload(paramsObj);
        }
      }
    }
  });
}

function messengerHandler() {
  var messengerBtn = document.getElementsByClassName('messengerShare')[0];

  if (!messengerBtn) return;

  var messengerUrl = 'https://www.facebook.com/dialog/send?app_id=' + squatch.user.facebook.appId + '&link=' + squatch.user.facebook.link + '&redirect_uri=' + squatch.user.facebook.redirectUrl;
  messengerBtn.href = messengerUrl;

  handleClicks(messengerBtn, function(e) {
    // If it's not mobile, don't use href link
    if (e.type != 'touchstart') {
      e.preventDefault();

      var url = messengerUrl + "&display=popup";
      window.open(url, 'fb-messenger', 'status=0,width=620,height=400');
    } else {
      window.open('fb-messenger://share/?link=' + squatch.user.facebook.link + '&app_id=' + squatch.user.facebook.appId);
    }

    if (window.frameElement && window.frameElement.squatchJsApi) {
      window.frameElement.squatchJsApi._shareEvent(window.squatch, 'FBMESSENGER');
    }
  });
}

function smsHandler() {
  var smsBtn = document.getElementsByClassName('smsShare')[0];

  if (!smsBtn) return;

  // Test url
  var smsUrl = 'sms:?&body=' + squatch.user.sms.body;
  smsBtn.href = smsUrl;

  var md = new MobileDetect('Version/4.0 Mobile Safari/534.30');
  var UA = md.userAgent();

  if (UA === 'Safari') {
    smsBtn.target = '_parent';
  }

  handleClicks(smsBtn, function(e) {
    if (window.frameElement && window.frameElement.squatchJsApi) {
      window.frameElement.squatchJsApi._shareEvent(window.squatch, 'SMS');
    }
  });
}

function whatsappHandler() {
  var whatsappBtn = document.getElementsByClassName('whatsappShare')[0];

  if (!whatsappBtn) return;

  var whatsappUrl = 'whatsapp://send?text=' + squatch.user.whatsapp.body;
  whatsappBtn.href = whatsappUrl;

  var md = new MobileDetect('Version/4.0 Mobile Safari/534.30');
  var UA = md.userAgent();

  if (UA === 'Safari') {
    whatsappBtn.target = '_parent';
  }

  handleClicks(whatsappBtn, function(e) {
    if (window.frameElement && window.frameElement.squatchJsApi) {
      window.frameElement.squatchJsApi._shareEvent(window.squatch, 'WHATSAPP');
    }
  });
}

function facebookHandler() {
  var facebookBtn = document.getElementsByClassName('fbShare')[0];

  if (!facebookBtn) return;

  var pictureString = (squatch.user.facebook.shareImage == "" || squatch.user.facebook.shareImage === null) ? "" : "&picture="+squatch.user.facebook.shareImage;
  var fbUrl = "https://www.facebook.com/dialog/feed?app_id=" + squatch.user.facebook.appId + "&link=" + squatch.user.facebook.link + "&name=" + squatch.user.facebook.title + "&description=" + squatch.user.facebook.summary + pictureString+ "&redirect_uri=" + squatch.user.facebook.redirectUrl;
  facebookBtn.href = fbUrl;

  handleClicks(facebookBtn, function(e) {
    // If it's not mobile, don't use href link
    if (e.type != 'touchstart') {
      e.preventDefault();

      var url = fbUrl + "&display=popup";
      window.open(url, 'fb', 'status=0,width=620,height=400');
    }

    if (window.frameElement && window.frameElement.squatchJsApi) {
      window.frameElement.squatchJsApi._shareEvent(window.squatch, 'FACEBOOK');
    }
  });
}

function twitterHandler() {
  var twitterBtn = document.getElementsByClassName('twShare')[0];
  var twUrl = "https://twitter.com/intent/tweet?source=webclient&text=" + squatch.user.twitter.message;

  if (!twitterBtn) return;
  twitterBtn.href = twUrl;

  handleClicks(twitterBtn, function(e) {
    if (e.type != 'touchstart') {
      e.preventDefault();
      window.open(twUrl, 'twitter', 'status=1,width=575,height=400');
    }

    if (window.frameElement && window.frameElement.squatchJsApi) {
      window.frameElement.squatchJsApi._shareEvent(window.squatch, 'TWITTER');
    }
  });
}

function emailHandler() {
  var emailBtn = document.getElementsByClassName('emailShare')[0];
  var emailUrl = squatch.user.email.share.mailToLink;

  if(!emailBtn) return;
  // emailBtn.href = emailUrl;

  var md = new MobileDetect('Version/4.0 Mobile Safari/534.30');
  var UA = md.userAgent();

  emailBtn.href = emailUrl;

  if (UA === 'Safari') {
    emailBtn.target = '_parent';

    handleClicks(emailBtn, function(e) {
      if (window.frameElement && window.frameElement.squatchJsApi) {
        window.frameElement.squatchJsApi._shareEvent(window.squatch, 'EMAIL');
      }
    });
  } else {
    handleClicks(emailBtn, function(e) {
      if (e.type != 'touchstart') {
        e.preventDefault();

        var mailurl = emailUrl;
        mailTo(mailurl);
      }

      if (window.frameElement && window.frameElement.squatchJsApi) {
        window.frameElement.squatchJsApi._shareEvent(window.squatch, 'EMAIL');
      }
    });
  }
}
<commit_msg>Change how the fb messneger link is set up<commit_after>function invalidInput(element, fn) {
  my_addClass(element, 'invalid');
  element.onkeypress = function() {
    if (fn(element.value)) {
      my_removeClass(this, 'invalid');
      my_addClass(this, 'valid');
    }
  }
}

function emailFormHandler() {
  var sendEmailBtn = document.getElementById('squatch-send-email');
  var firstName = document.getElementById('squatch-user-firstname');
  var lastName = document.getElementById('squatch-user-lastname');
  var emailInput = document.getElementById('squatch-user-email');

  handleClicks(sendEmailBtn, function() {
    var noErrors = true;

    if (firstName && firstName.value.length < 1) {
      noErrors = false;
      invalidInput(firstName, function(e) { return e.length < 1; });
    }

    if (lastName && lastName.value.length < 1) {
      noErrors = false;
      invalidInput(lastName, function(e) { return e.length < 1; });
    }

    if (!isValidEmail(emailInput.value)) {
      noErrors = false;
      invalidInput(emailInput, function(e) { return isValidEmail(e); });
    }

    if (noErrors) {
      var paramsObj = {};

      if (firstName) {
        my_removeClass(firstName, 'invalid');
        paramsObj.firstName = firstName.value;
      }

      if (lastName) {
         my_removeClass(lastName, 'invalid');
         paramsObj.lastName = lastName.value;
      }

      if (emailInput) {
        my_removeClass(emailInput, 'invalid');
        paramsObj.email = emailInput.value;
      }

      if (window.frameElement && window.frameElement.squatchJsApi) {
        var widget = window.frameElement.squatchJsApi;

        if (window.parent.squatch && window.parent.squatch.widgets().eventBus) {
          window.parent.squatch.widgets().eventBus.dispatch('submit_email', this, widget, paramsObj);
        } else {
          window.frameElement.squatchJsApi.reload(paramsObj);
        }
      }
    }
  });
}

function messengerHandler() {
  var messengerBtn = document.getElementsByClassName('messengerShare')[0];

  if (!messengerBtn) return;

  var messengerUrl = 'fb-messenger://share/?link=' + squatch.user.facebook.link + '&app_id=' + squatch.user.facebook.appId;
  messengerBtn.href = messengerUrl;

  handleClicks(messengerBtn, function(e) {
    // If it's not mobile, don't use href link
    if (e.type != 'touchstart') {
      e.preventDefault();

      var url = 'https://www.facebook.com/dialog/send?app_id=' + squatch.user.facebook.appId + '&link=' + squatch.user.facebook.link + '&redirect_uri=' + squatch.user.facebook.redirectUrl + "&display=popup";
      window.open(url, 'fb-messenger', 'status=0,width=620,height=400');
    }

    if (window.frameElement && window.frameElement.squatchJsApi) {
      window.frameElement.squatchJsApi._shareEvent(window.squatch, 'FBMESSENGER');
    }
  });
}

function smsHandler() {
  var smsBtn = document.getElementsByClassName('smsShare')[0];

  if (!smsBtn) return;

  // Test url
  var smsUrl = 'sms:?&body=' + squatch.user.sms.body;
  smsBtn.href = smsUrl;

  var md = new MobileDetect('Version/4.0 Mobile Safari/534.30');
  var UA = md.userAgent();

  if (UA === 'Safari') {
    smsBtn.target = '_parent';
  }

  handleClicks(smsBtn, function(e) {
    if (window.frameElement && window.frameElement.squatchJsApi) {
      window.frameElement.squatchJsApi._shareEvent(window.squatch, 'SMS');
    }
  });
}

function whatsappHandler() {
  var whatsappBtn = document.getElementsByClassName('whatsappShare')[0];

  if (!whatsappBtn) return;

  var whatsappUrl = 'whatsapp://send?text=' + squatch.user.whatsapp.body;
  whatsappBtn.href = whatsappUrl;

  var md = new MobileDetect('Version/4.0 Mobile Safari/534.30');
  var UA = md.userAgent();

  if (UA === 'Safari') {
    whatsappBtn.target = '_parent';
  }

  handleClicks(whatsappBtn, function(e) {
    if (window.frameElement && window.frameElement.squatchJsApi) {
      window.frameElement.squatchJsApi._shareEvent(window.squatch, 'WHATSAPP');
    }
  });
}

function facebookHandler() {
  var facebookBtn = document.getElementsByClassName('fbShare')[0];

  if (!facebookBtn) return;

  var pictureString = (squatch.user.facebook.shareImage == "" || squatch.user.facebook.shareImage === null) ? "" : "&picture="+squatch.user.facebook.shareImage;
  var fbUrl = "https://www.facebook.com/dialog/feed?app_id=" + squatch.user.facebook.appId + "&link=" + squatch.user.facebook.link + "&name=" + squatch.user.facebook.title + "&description=" + squatch.user.facebook.summary + pictureString+ "&redirect_uri=" + squatch.user.facebook.redirectUrl;
  facebookBtn.href = fbUrl;

  handleClicks(facebookBtn, function(e) {
    // If it's not mobile, don't use href link
    if (e.type != 'touchstart') {
      e.preventDefault();

      var url = fbUrl + "&display=popup";
      window.open(url, 'fb', 'status=0,width=620,height=400');
    }

    if (window.frameElement && window.frameElement.squatchJsApi) {
      window.frameElement.squatchJsApi._shareEvent(window.squatch, 'FACEBOOK');
    }
  });
}

function twitterHandler() {
  var twitterBtn = document.getElementsByClassName('twShare')[0];
  var twUrl = "https://twitter.com/intent/tweet?source=webclient&text=" + squatch.user.twitter.message;

  if (!twitterBtn) return;
  twitterBtn.href = twUrl;

  handleClicks(twitterBtn, function(e) {
    if (e.type != 'touchstart') {
      e.preventDefault();
      window.open(twUrl, 'twitter', 'status=1,width=575,height=400');
    }

    if (window.frameElement && window.frameElement.squatchJsApi) {
      window.frameElement.squatchJsApi._shareEvent(window.squatch, 'TWITTER');
    }
  });
}

function emailHandler() {
  var emailBtn = document.getElementsByClassName('emailShare')[0];
  var emailUrl = squatch.user.email.share.mailToLink;

  if(!emailBtn) return;
  // emailBtn.href = emailUrl;

  var md = new MobileDetect('Version/4.0 Mobile Safari/534.30');
  var UA = md.userAgent();

  emailBtn.href = emailUrl;

  if (UA === 'Safari') {
    emailBtn.target = '_parent';

    handleClicks(emailBtn, function(e) {
      if (window.frameElement && window.frameElement.squatchJsApi) {
        window.frameElement.squatchJsApi._shareEvent(window.squatch, 'EMAIL');
      }
    });
  } else {
    handleClicks(emailBtn, function(e) {
      if (e.type != 'touchstart') {
        e.preventDefault();

        var mailurl = emailUrl;
        mailTo(mailurl);
      }

      if (window.frameElement && window.frameElement.squatchJsApi) {
        window.frameElement.squatchJsApi._shareEvent(window.squatch, 'EMAIL');
      }
    });
  }
}
<|endoftext|>


<commit_before>'use babel'

/* @flow */

export type UCompiler$Plugin = {
  compiler: boolean,
  minifier: boolean,
  process: ((parameters: UCompiler$Job) => string)
}

export type UCompiler$Job = {
  rootPath: string,
  filePath: string,
  contents: string,
  state: Object,
  config: Object
}

export type Ucompiler$Config = {
  defaultRule: string,
  rules: Map<string, Ucompiler$Config$Rule>
}

export type Ucompiler$Config$Rule = {
  plugins: Array<string>,
  include: Array<{
    directory: string,
    deep?: boolean,
    extensions: Array<string>
  }>,
  exclude?: Array<string>,
  outputPath: string,
  sourceMap?: string
}
<commit_msg>:art: Tweak configuration schema<commit_after>'use babel'

/* @flow */

export type UCompiler$Plugin = {
  compiler: boolean,
  minifier: boolean,
  process: ((parameters: UCompiler$Job) => string)
}

export type UCompiler$Job = {
  rootPath: string,
  filePath: string,
  contents: string,
  state: Object,
  config: Object
}

export type Ucompiler$Config = {
  defaultRule: string,
  rules: Array<Ucompiler$Config$Rule>
}

export type Ucompiler$Config$Rule = {
  name: string,
  plugins: Array<string>,
  include: Array<{
    directory: string,
    deep?: boolean,
    extensions: Array<string>
  }>,
  exclude?: Array<string>,
  outputPath: string,
  sourceMap?: string
}
<|endoftext|>


<commit_before>/**
 * Created by bryangill on 4/9/16.
 */
import MediaController from './media.c.js';

function media() {
    return {
        scope: {
            mediaId: '@'
        },
        controllerAs: "mediaCtrl",
        controller: MediaController,
        link: function (scope, element, attrs, mediaCtrl) {
            mediaCtrl.retrieveMedia(attrs.mediaId).then(function (response) {
                element.css({
                    'background-image': 'url(data:image/*;base64,' + response.data.guid + ')',
                    'width': '1024px',
                    'height': '768px'
                });
            })
        }
    };
}

export default media;<commit_msg>Remove defined height and width<commit_after>/**
 * Created by bryangill on 4/9/16.
 */
import MediaController from './media.c.js';

function media() {
    return {
        scope: {
            mediaId: '@'
        },
        controllerAs: "mediaCtrl",
        controller: MediaController,
        link: function (scope, element, attrs, mediaCtrl) {
            mediaCtrl.retrieveMedia(attrs.mediaId).then(function (response) {
                element.css({
                    'background-image': 'url(data:image/*;base64,' + response.data.guid + ')'
                });
            })
        }
    };
}

export default media;<|endoftext|>


<commit_before>/**
 * Copyright 2012 Palomino Labs, Inc.
 *
 * 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.
 */

/**
 * A proxy for communicating with StackMob's REST API.
 *
 * @author Tyler Wolf
 */
Ext.define("Ux.palominolabs.stackmob.data.proxy.StackMob", {
    extend: 'Ext.data.proxy.Rest',
    alias: 'proxy.stackmob',

    conn: Ux.palominolabs.stackmob.data.StackMobConnector,

    config: {
        // Disable cache busting / paging for now, since StackMob rejects the GET params added by ServerProxy.
        // TODO: re-implement these in a StackMob-compliant manner (request headers)
        noCache: false,
        pageParam: false,
        startParam: false,
        limitParam: false
    },

    /**
     * Specialized version of getHeaders which merges in the required OAuth 2.0 headers for StackMob
     * @return {Object} Headers
     */
    getHeaders: function() {
        var me = this;
        return Ext.applyIf(me._headers || {}, me.getStandardHeaders());
    },

    /**
     * Specialized version of buildRequest which assembles the correct headers for StackMob.
     * @param {Ext.data.Operation} operation The {@link Ext.data.Operation Operation} object to execute
     * @return {Ext.data.Request} The request object
     */
    buildRequest: function(operation) {
        var me = this,
            params = Ext.applyIf(operation.getParams() || {}, me.getExtraParams() || {}),
            headers = me.getHeaders(),
            request;

        //copy any sorters, filters etc into the params so they can be sent over the wire
        // TODO: undo this and re-implement in a StackMob-compliant manner (request headers)
        params = Ext.applyIf(params, me.getParams(operation));

        request = Ext.create('Ext.data.Request', {
            headers  : headers,
            params   : params,
            action   : operation.getAction(),
            records  : operation.getRecords(),
            url      : operation.getUrl(),
            operation: operation,
            proxy    : me
        });

        request.setUrl(me.buildUrl(request));
        operation.setRequest(request);

        return request;
    },

    /**
     * Specialized version of buildUrl which returns the appropriate StackMob API URL
     * @param {Ext.data.Request} request The request object
     * @return {String} The URL
     */
    buildUrl: function(request) {
        var me = this;
        return [me.conn.getUrlRoot(), me.callParent(arguments)].join('');
    },

    /**
     * Assembles an object containing the standard headers required for communication with StackMob's
     * REST API using OAuth 2.0
     * @return {Object} Headers
     */
    getStandardHeaders: function() {
        var me = this;
        return {
            'Accept': ['application/vnd.stackmob+json; version=', me.conn.getApiVersion()].join(""),
            'X-StackMob-API-Key': me.conn.getPublicKey(),
            'X-StackMob-Proxy-Plain': 'stackmob-api',
            'X-StackMob-User-Agent': ['StackMob (', me.conn.getSdkName(),'; ', me.conn.getSdkVersion(), ')/', me.conn.getAppName()].join("")
        };
    }

});<commit_msg>Added paging support<commit_after>/**
 * Copyright 2012 Palomino Labs, Inc.
 *
 * 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.
 */

/**
 * A proxy for communicating with StackMob's REST API.
 *
 * @author Tyler Wolf
 */
Ext.define("Ux.palominolabs.stackmob.data.proxy.StackMob", {
    extend: 'Ext.data.proxy.Rest',
    alias: 'proxy.stackmob',

    conn: Ux.palominolabs.stackmob.data.StackMobConnector,

    config: {
        // Disable cache busting / paging for now, since StackMob rejects the GET params added by ServerProxy.
        // TODO: re-implement these in a StackMob-compliant manner (request headers)
        noCache: false,
        pageParam: false,
        startParam: false,
        limitParam: false
    },

    /**
     * Specialized version of getHeaders which merges in the required OAuth 2.0 headers for StackMob
     * @return {Object} Headers
     */
    getHeaders: function() {
        var me = this;
        return Ext.applyIf(me._headers || {}, me._getStandardHeaders());
    },

    /**
     * Specialized version of buildRequest which assembles the correct headers for StackMob.
     * @param {Ext.data.Operation} operation The {@link Ext.data.Operation Operation} object to execute
     * @return {Ext.data.Request} The request object
     */
    buildRequest: function(operation) {
        var me = this,
            params = Ext.applyIf(operation.getParams() || {}, me.getExtraParams() || {}),
            headers = me.getHeaders(),
            request;

        //copy any sorters, filters etc into the params so they can be sent over the wire
        // TODO: undo this and re-implement in a StackMob-compliant manner (request headers)
        params = Ext.applyIf(params, me.getParams(operation));

        request = Ext.create('Ext.data.Request', {
            headers  : headers,
            params   : params,
            action   : operation.getAction(),
            records  : operation.getRecords(),
            url      : operation.getUrl(),
            operation: operation,
            proxy    : me
        });

        request.setUrl(me.buildUrl(request));
        operation.setRequest(request);

        return request;
    },

    /**
     * Specialized version of doRequest with operation-specific headers
     * @protected
     */
    doRequest: function(operation, callback, scope) {
        var me = this,
            writer  = me.getWriter(),
            request = me.buildRequest(operation),
            headers = Ext.applyIf(me.getHeaders(), me._getAdditionalHeaders(operation));

        request.setConfig({
            headers        : headers,
            timeout        : me.getTimeout(),
            method         : me.getMethod(request),
            callback       : me.createRequestCallback(request, operation, callback, scope),
            scope          : me
        });

        if (operation.getWithCredentials() || me.getWithCredentials()) {
            request.setWithCredentials(true);
        }

        // We now always have the writer prepare the request
        request = writer.write(request);

        Ext.Ajax.request(request.getCurrentConfig());

        return request;
    },

    /**
     * Specialized version of buildUrl which returns the appropriate StackMob API URL
     * @param {Ext.data.Request} request The request object
     * @return {String} The URL
     */
    buildUrl: function(request) {
        var me = this;
        return [me.conn.getUrlRoot(), me.callParent(arguments)].join('');
    },

    /**
     * Assembles an object containing the standard headers required for communication with StackMob's
     * REST API using OAuth 2.0
     * @return {Object} Headers
     */
    _getStandardHeaders: function() {
        var me = this;

        return {
            'Accept': ['application/vnd.stackmob+json; version=', me.conn.getApiVersion()].join(""),
            'X-StackMob-API-Key': me.conn.getPublicKey(),
            'X-StackMob-Proxy-Plain': 'stackmob-api',
            'X-StackMob-User-Agent': ['StackMob (', me.conn.getSdkName(),'; ', me.conn.getSdkVersion(), ')/', me.conn.getAppName()].join("")
        };
    },

    /**
     * Assembles an object containing additional headers, such as paging
     * @param {Ext.data.Operation} operation The operation
     * @return {Object} Headers
     * @private
     */
    _getAdditionalHeaders: function(operation) {
        var me = this,
            headers = {},
            start = operation.getStart(),
            limit = operation.getLimit(),
            end;

        if (me.getEnablePagingParams() && (start !== null) && (limit !== null)) {
            end = start + limit - 1;
            headers['Range'] = ['objects=', start, '-', end].join("");
        }

        return headers;
    }

});<|endoftext|>


<commit_before>/**
 * Created with IntelliJ IDEA.
 * User: bbhagan
 * Date: 6/26/13
 * Time: 1:33 PM
 * To change this template use File | Settings | File Templates.
 */

$(document).ready(function() {
   $('#tour').bind('resize', function(event) {
      $('#tour').css({'min-height': 768});
      $('#tour').css({'min-width': 1024});
      //alert('orientation change');
   });

   $("#getStartedFormSubmit").on("click", function(e){
      transitionToStartTasks(e);
   });

   $("#doneWithTasksButton").on("click", function(e){
      transitionToStartGoals(e);
   });

   $('#configureTasksRepeats').on('change', function(e) {
      swapConfigureTasksRepeats(e);
   })

   $('#configureRepeatPayment').on('change', function(e) {
      swapConfigureRepeatPayment(e);
   })
   $('#configureNonRepeatPayment').on('change', function(e) {
      swapConfigureNonRepeatPayment(e);
   })

});

var tykoonData = {
   parent: {
      children: []
   },
   currentChildIndex : 0
};
var currentChild;

var transitionToStartTasks = function(e) {

   // populate main data object
   var name = $('#getStartedFormChildFirstName').val();
   var birthdayString = $('#getStartedFormChildBirthday').val();
   // -1 on month, apparently 0-based for months
   var birthday = new Date(parseInt(birthdayString.substring(0,4)), parseInt(birthdayString.substring(5,7))-1, parseInt(birthdayString.substring(8)));
   var gender = $("input:radio[name='getStartedFormChildGender']:checked").val();
   var child = new Child(0, name, '', '', '', birthday, 0, gender);
   tykoonData.parent.children.push(child);

   currentChild = child;
   populateTasksForChild(child);

};

var configureTasks = function(e) {
   // FInd the task clicked on and collect it's data
   var taskltem = $(e.currentTarget),
      taskName = $(taskltem).find(".title").text();

   var task = new Task(0, taskName, '', '', '', '');  // new Task(id, name, repeatDays, payType, payAmt, dueDate);

   // populate the popup disclosure and show it
   $('#configureTasks .taskTitle').html(task.name);
   $("#configureTasks").popup().popup("open", {transition: "pop"} );
};

var populateTasksForChild = function(child) {
  //populate page with child data
  $(".childFirstName").html(child.name);
  $(".childAge").html(child.getAge());
  $(".childGender").html(child.getGenderNoun());

  //clean page and populate page with tasks from catalog
 $('#startTasks .taskCatalog .tasks').empty();
 var taskTemplate = $("#startTasks .taskCatalog .taskTemplate .taskItem")[0];
  for(var i in cannedTasks.tasks) {
    var task = cannedTasks.tasks[i];
    if ((task.gender == "b" || task.gender == child.gender) && (child.getAge() >= task.ageRange.min && child.getAge() <= task.ageRange.max)) {
      var taskItem = $(taskTemplate).clone()
      $(taskItem).find(".title").html(task.name);
      $(taskItem).find(".numKids span").html(task.numPeople);
      // var html = '

' + task.name + '

' + task.numPeople + ' kids are doing this

';
      $('#startTasks .taskCatalog .tasks').append($(taskItem));
    }
  }

  // hook up the taps on taskItems to configure them
  $("#startTasks .taskCatalog .taskItem").on("click", function(e){
     configureTasks(e);
  });
};

var swapConfigureTasksRepeats = function(e) {
   if ($("input:radio[name='configureTasksRepeats']:checked").val() == 1) {
      $('#configureTasks .hideNonRepeat').hide();
      $('#configureTasks .hideRepeat').show();
   } else {
      $('#configureTasks .hideNonRepeat').show();
      $('#configureTasks .hideRepeat').hide();
   }
};

var swapConfigureRepeatPayment = function(e) {
   if ($("input:radio[name='configureRepeatPayment']:checked").val() == 'allowance') {
      $('#configureTasks .taskRepeatPaymentDetails .resp').hide();
      $('#configureTasks .taskRepeatPaymentDetails .allow').show();
   } else {
     $('#configureTasks .taskRepeatPaymentDetails .resp').show();
     $('#configureTasks .taskRepeatPaymentDetails .allow').hide();
   }
};
var swapConfigureNonRepeatPayment = function(e) {
   if ($("input:radio[name='configureNonRepeatPayment']:checked").val() == 'money') {
      $('#configureTasks .taskNonRepeatPaymentDetails .resp').hide();
      $('#configureTasks .taskNonRepeatPaymentDetails .money').show();
   } else {
     $('#configureTasks .taskNonRepeatPaymentDetails .resp').show();
     $('#configureTasks .taskNonRepeatPaymentDetails .money').hide();
   }
};

/* ADD GOALS section */

var transitionToStartGoals = function(e) {

  populateProductsForChild(currentChild);
  $(".addTaskContent, .startTasksFooter").fadeOut(200);

  // move the cover
  $(".cover").addClass("leftCover").css("left","0");

  $(".addGoalContent, .startGoalsFooter").delay(200).fadeIn(200);
}

var populateProductsForChild = function(child) {

  //clean page and populate page with tasks from catalog
 $('#startTasks .productCatalog .goals').empty();
 var productTemplate = $("#startTasks .productCatalog .productTemplate .productItem")[0];
  for(var i in cannedProducts.products) {
    var product = cannedProducts.products[i];
    if ((product.gender == "b" || product.gender == child.gender) && (child.getAge() >= product.ageRange.min && child.getAge() <= product.ageRange.max)) {
      var productItem = $(productTemplate).clone();
      $(productItem).find(".title").html(product.name);
      $(productItem).find(".numKids span").html(product.numPeople);
      $('#startTasks .productCatalog .products').append($(productItem));
    }
  }

  // hook up the taps on productItems to configure them
  $("#startTasks .productCatalog .productItem").on("click", function(e){
     showProductDetails(e);
  });
};

var showProductDetails = function(e) {
  var productItem = $(e.currentTarget),
      productName = $(productltem).find(".title").text();
  alert("tapped on: " + productName);
}

/* ======== TEST DATA, comment me out to run for real ===========  */

var testBdayString = '2006-10-29';
var testBirthday = new Date(parseInt(testBdayString.substring(0,4)), parseInt(testBdayString.substring(5,7))-1, parseInt(testBdayString.substring(8)));
currentChild = new Child(0, 'Kaiya', '', '', '', testBirthday, 0, 'f');
tykoonData.parent.children.push(currentChild);
populateTasksForChild(currentChild);

/* ======== END TEST DATA  ============================ */
<commit_msg>fixed typo<commit_after>/**
 * Created with IntelliJ IDEA.
 * User: bbhagan
 * Date: 6/26/13
 * Time: 1:33 PM
 * To change this template use File | Settings | File Templates.
 */

$(document).ready(function() {
   $('#tour').bind('resize', function(event) {
      $('#tour').css({'min-height': 768});
      $('#tour').css({'min-width': 1024});
      //alert('orientation change');
   });

   $("#getStartedFormSubmit").on("click", function(e){
      transitionToStartTasks(e);
   });

   $("#doneWithTasksButton").on("click", function(e){
      transitionToStartGoals(e);
   });

   $('#configureTasksRepeats').on('change', function(e) {
      swapConfigureTasksRepeats(e);
   })

   $('#configureRepeatPayment').on('change', function(e) {
      swapConfigureRepeatPayment(e);
   })
   $('#configureNonRepeatPayment').on('change', function(e) {
      swapConfigureNonRepeatPayment(e);
   })

});

var tykoonData = {
   parent: {
      children: []
   },
   currentChildIndex : 0
};
var currentChild;

var transitionToStartTasks = function(e) {

   // populate main data object
   var name = $('#getStartedFormChildFirstName').val();
   var birthdayString = $('#getStartedFormChildBirthday').val();
   // -1 on month, apparently 0-based for months
   var birthday = new Date(parseInt(birthdayString.substring(0,4)), parseInt(birthdayString.substring(5,7))-1, parseInt(birthdayString.substring(8)));
   var gender = $("input:radio[name='getStartedFormChildGender']:checked").val();
   var child = new Child(0, name, '', '', '', birthday, 0, gender);
   tykoonData.parent.children.push(child);

   currentChild = child;
   populateTasksForChild(child);

};

var configureTasks = function(e) {
   // FInd the task clicked on and collect it's data
   var taskltem = $(e.currentTarget),
      taskName = $(taskltem).find(".title").text();

   var task = new Task(0, taskName, '', '', '', '');  // new Task(id, name, repeatDays, payType, payAmt, dueDate);

   // populate the popup disclosure and show it
   $('#configureTasks .taskTitle').html(task.name);
   $("#configureTasks").popup().popup("open", {transition: "pop"} );
};

var populateTasksForChild = function(child) {
  //populate page with child data
  $(".childFirstName").html(child.name);
  $(".childAge").html(child.getAge());
  $(".childGender").html(child.getGenderNoun());

  //clean page and populate page with tasks from catalog
 $('#startTasks .taskCatalog .tasks').empty();
 var taskTemplate = $("#startTasks .taskCatalog .taskTemplate .taskItem")[0];
  for(var i in cannedTasks.tasks) {
    var task = cannedTasks.tasks[i];
    if ((task.gender == "b" || task.gender == child.gender) && (child.getAge() >= task.ageRange.min && child.getAge() <= task.ageRange.max)) {
      var taskItem = $(taskTemplate).clone()
      $(taskItem).find(".title").html(task.name);
      $(taskItem).find(".numKids span").html(task.numPeople);
      // var html = '

' + task.name + '

' + task.numPeople + ' kids are doing this

';
      $('#startTasks .taskCatalog .tasks').append($(taskItem));
    }
  }

  // hook up the taps on taskItems to configure them
  $("#startTasks .taskCatalog .taskItem").on("click", function(e){
     configureTasks(e);
  });
};

var swapConfigureTasksRepeats = function(e) {
   if ($("input:radio[name='configureTasksRepeats']:checked").val() == 1) {
      $('#configureTasks .hideNonRepeat').hide();
      $('#configureTasks .hideRepeat').show();
   } else {
      $('#configureTasks .hideNonRepeat').show();
      $('#configureTasks .hideRepeat').hide();
   }
};

var swapConfigureRepeatPayment = function(e) {
   if ($("input:radio[name='configureRepeatPayment']:checked").val() == 'allowance') {
      $('#configureTasks .taskRepeatPaymentDetails .resp').hide();
      $('#configureTasks .taskRepeatPaymentDetails .allow').show();
   } else {
     $('#configureTasks .taskRepeatPaymentDetails .resp').show();
     $('#configureTasks .taskRepeatPaymentDetails .allow').hide();
   }
};
var swapConfigureNonRepeatPayment = function(e) {
   if ($("input:radio[name='configureNonRepeatPayment']:checked").val() == 'money') {
      $('#configureTasks .taskNonRepeatPaymentDetails .resp').hide();
      $('#configureTasks .taskNonRepeatPaymentDetails .money').show();
   } else {
     $('#configureTasks .taskNonRepeatPaymentDetails .resp').show();
     $('#configureTasks .taskNonRepeatPaymentDetails .money').hide();
   }
};

/* ADD GOALS section */

var transitionToStartGoals = function(e) {

  populateProductsForChild(currentChild);
  $(".addTaskContent, .startTasksFooter").fadeOut(200);

  // move the cover
  $(".cover").addClass("leftCover").css("left","0");

  $(".addGoalContent, .startGoalsFooter").delay(200).fadeIn(200);
}

var populateProductsForChild = function(child) {

  //clean page and populate page with tasks from catalog
 $('#startTasks .productCatalog .goals').empty();
 var productTemplate = $("#startTasks .productCatalog .productTemplate .productItem")[0];
  for(var i in cannedProducts.products) {
    var product = cannedProducts.products[i];
    if ((product.gender == "b" || product.gender == child.gender) && (child.getAge() >= product.ageRange.min && child.getAge() <= product.ageRange.max)) {
      var productItem = $(productTemplate).clone();
      $(productItem).find(".title").html(product.name);
      $(productItem).find(".numKids span").html(product.numPeople);
      $('#startTasks .productCatalog .products').append($(productItem));
    }
  }

  // hook up the taps on productItems to configure them
  $("#startTasks .productCatalog .productItem").on("click", function(e){
     showProductDetails(e);
  });
};

var showProductDetails = function(e) {
  var productItem = $(e.currentTarget),
      productName = $(productItem).find(".title").text();
  alert("tapped on: " + productName);
}

/* ======== TEST DATA, comment me out to run for real ===========  */

var testBdayString = '2006-10-29';
var testBirthday = new Date(parseInt(testBdayString.substring(0,4)), parseInt(testBdayString.substring(5,7))-1, parseInt(testBdayString.substring(8)));
currentChild = new Child(0, 'Kaiya', '', '', '', testBirthday, 0, 'f');
tykoonData.parent.children.push(currentChild);
populateTasksForChild(currentChild);

/* ======== END TEST DATA  ============================ */
<|endoftext|>