<commit_before>/**
* Doydoy Clone
*
* @brief JQuery plugin to clone a group of elements with the management of ids
*
* @author doydoy44
* @version 1.0
*
*/

(function($) {
    /////////////////////////////////////////////////////
    // Variables globales au plugin mais prive        //
    // (non accessible en dehors du plugin)            //
    /////////////////////////////////////////////////////
    // nbre de clonage pour viter d'avoir les mmes ids
    var doydoy_counter = 0;
    // nouvel id du conteneur(parent) cr
    var doydoy_new_id = null;
    // prfix d'un nouvel id au cas o l'id n'existerait pas
    var glob_prefix_new_elt = "id_doydoy_clone_";
    // Liste de tous les lments cloner depuis le dbut
    var doydoy_all_clones = [];
    // Liste de tous les lments cloner lors du dernier clonage
    var doydoy_last_clones = [];

    //////////////////////////////////////////////////////////
    // LISTE DES FONCTIONS DISPONIBLES EN DEHORS DU CLONAGE //
    //////////////////////////////////////////////////////////
    // Rcupration du nombre de clonage effectu
    $.fn.doydoyGetCounter = function(){
        return doydoy_counter;
    }

    // Rcupration de la liste de tous les lments cloner depuis le dbut
    $.fn.doydoyGetAllClones = function(){
        return doydoy_all_clones;
    }

    // Rcupration de la liste de tous les lments cloner lors du dernier clonage
    $.fn.doydoyGetLastClones = function(){
        return doydoy_last_clones;
    }

    // Rcupration de l'id du dernier conteneur (parent) cr
    $.fn.doydoyGetLastNewId = function(){
        return doydoy_new_id;
    }

    // Affectation du prfix pour un nouvel id au cas o l'id n'existerait pas
    $.fn.doydoySetPrefixNewId = function(prefix_new_elt){
        glob_prefix_new_elt = prefix_new_elt;
        return this;
    }

    // Rinitialisation de la liste de tous les lments cloner depuis le dbut
    $.fn.initAllClonesList = function(){
        doydoy_all_clones = [];
        return this;
    }

    /////////////////////////////////////////////////////
    // LISTE DES METHODES RACCOURCIES                  //
    /////////////////////////////////////////////////////
    // Mthode after pour le clonage
    $.fn.doydoyCloneAfter = function(params){
        params = $.extend( params, {method : "after"});
        return this.doydoyClone(params);
    }
    // Mthode before pour le clonage
    $.fn.doydoyCloneBefore = function(params){
        params = $.extend( params, {method : "before"});
        return this.doydoyClone(params);
    }
    // Mthode append pour le clonage
    $.fn.doydoyCloneAppend = function(params){
        params = $.extend( params, {method : "append"});
        return this.doydoyClone(params);
    }
    // Mthode prepend pour le clonage
    $.fn.doydoyClonePrepend = function(params){
        params = $.extend( params, {method : "prepend"});
        return this.doydoyClone(params);
    }

    /////////////////////////////////////////////////////
    // Plugin de clonage                               //
    /////////////////////////////////////////////////////
    $.fn.doydoyClone = function(params) {
        // type de traitement pour la fonction eval (after par dfaut)
        var function_plugin_name = 'after';

        // Fusionner les paramtres par dfaut et ceux de l'utilisateur
        params = $.extend( {
                            method         : "",
                            target         : "",
                            impact_name    : true,
                            impact_for     : true,
                            new_name       : false,
                            new_all_name   : false,
                            new_all_id     : false,
                            prefix_new_elt : glob_prefix_new_elt
                            },
                            params);

        if (params.new_all_name)
            params.new_name = true;

        // Incrmentation du compter pour commencer  avoir des id  partir de 1 (idfoo_1) et suprieur au dernier clonage
        doydoy_counter++;

        // Rcupration du type de traitement pour la fonction eval (after par dfaut)
        switch (params.method) {
            case "after":
            case "before":
            case "append":
            case "prepend":
                function_plugin_name = params.method;
                break;
            default:
                function_plugin_name = 'after';
                break;
        }

        // Traverser tous les nuds.
        this.each(function() {
            // id sans le numro d'incrmentation du futur conteneur (parent)
            var id_elt;
            // lment  cloner
            var elt_a_cloner = this;
            // numro d'incrmentation du futur conteneur (parent)
            var doydoy_counter_clone = doydoy_counter;

            // Initialisation des derniers lments clons
            doydoy_last_clones = [];

            // Initialisation du nouvel id
            doydoy_new_id = null;

            // Dfinition de l'id (sans le numro d'incrmentation) du futur conteneur (parent)
            if ($(this).attr('id') == undefined){
                if ($(this).attr('name') != undefined)
                    id_elt = params.prefix_new_elt + $(this).attr('name');
                else
                    id_elt = params.prefix_new_elt + $(this).prop('tagName');
            }
            else
                id_elt = $(this).attr('id');

            // Rcupration de l'lment  qui rajouter les lments clons et y affecter la mthode after, before, ...
            // si non renseign, on prend l'lment  cloner
            if (params.target != "")
                dernier_element = params.target;
            else
                dernier_element = $(this);

            // Clonage de l'ensemble des lments
            function function_clone(){

                // retour de l'ensemble des lements clons
                return $(elt_a_cloner).clone(true).each(function(){
                    // Dtermination de l'd du parent clon
                    doydoy_new_id = id_elt + "_" + doydoy_counter_clone;

                    $(this).attr('id', doydoy_new_id);

                    // Dtermination du nouveau nom du parent clon si on a choisi l'option
                    var new_name = "";
                    if (typeof($(this).attr('name')) != 'undefined'){
                        new_name = $(this).attr('name');
                        if (params.new_name || params.impact_name){
                            new_name += "_" + doydoy_counter_clone;
                            $(this).attr('name', new_name);
                        }
                    }
                    else{
                        if (params.new_name){
                            new_name = doydoy_new_id;
                            $(this).attr('name', new_name);
                        }
                    }

                    // Changement de l'attribut for qui fait rfrence  l'ancien id d'un input + "_" + numro de clonage
                    if (typeof($(this).attr('for')) != 'undefined'){
                        if (params.impact_for){
                            $(this).attr('for', $(this).attr('for') + "_" + doydoy_counter_clone);
                        }
                    }

                    // Sauvegarde de ce nouveau parent dans la liste de tous les lments clons depuis le dbut
                    if (typeof(doydoy_all_clones['"' + doydoy_counter_clone + '"']) == 'undefined'){
                        doydoy_all_clones['"' + doydoy_counter_clone + '"'] = [];
                    }

                    doydoy_all_clones['"' + doydoy_counter_clone + '"']['parent'] = {id        : doydoy_new_id,
                                                                                id_before : id_elt,
                                                                                num_clone : doydoy_counter_clone,
                                                                                name      : new_name,
                                                                                elt       : $(this)};
                    // Sauvegarde de ce nouveau parent dans la liste de tous les lments clons lors du dernier clonage
                    doydoy_last_clones['parent'] = {id        : doydoy_new_id,
                                                    id_before : id_elt,
                                                    num_clone : doydoy_counter_clone,
                                                    name      : new_name,
                                                    elt       : $(this)};
                    // incrmentation du numro de clonage pour viter d'avoir les mmes ids
                    doydoy_counter_clone++;
                });
            }

            // Ajout de l'ensemble clon  l'lment choisi avec la mthode choisie (after, begin, prepend, append)
            eval("$(dernier_element).each(function(){ $(this)." + function_plugin_name + "(function_clone())})");

            // Initialisation de la liste des derniers enfants crs
            doydoy_last_clones['child'] = [];

            // Numro de l'enfant par rapport  son parent
            var cpt_child = 0;
            // id d'origine de l'enfant avant son nouvel id
            var id_before = "";
            // nouvel id de l'enfant
            var new_id = "";
            // nouveau nom de l'enfant
            var new_name = "";

            // R-attribution des ids des lements des conteneurs qui ont t crs
            for(var i = doydoy_counter; i < (doydoy_counter_clone); i++){
                cpt_child = 0;

                // parcourt de tous les enfants du conteneur
                $("#" + id_elt + "_" + i + " *").each(function(){
                    // Dtermination du nouvel id de l'enfant en cours
                    if (typeof($(this).attr('id')) != 'undefined'){
                        // rcupration de l'id d'origine de l'enfant
                        id_before = $(this).attr('id');
                        new_id    = id_before + "_" + i;
                        // changement de l'id
                        $(this).attr('id', new_id);
                    }
                    else {
                        // Initialisation de l'id d'origine et du nouvel id (car il n'en avait pas forcment)
                        id_before = "";
                        if (params.new_all_id){
                            if ($(this).attr('name') != undefined)
                                new_id = params.prefix_new_elt + $(this).attr('name') + "_" + i;
                            else
                                new_id = params.prefix_new_elt + $(this).prop('tagName') + "_" + i;
                            // Changement de l'id
                            $(this).attr('id', new_id);
                        }
                        else
                            new_id = "";
                    }

                    // Changement du nom si on l'a demand (params.new_name : true)
                    if (typeof($(this).attr('name')) != 'undefined'){
                        new_name = $(this).attr('name');
                        if (params.new_all_name || params.impact_name){
                            new_name += "_" + i;
                            $(this).attr('name', new_name);
                        }
                    }
                    else{
                        if (params.new_all_name) {
                            if (new_id != "")
                                new_name = new_id;
                            else
                                new_name = params.prefix_new_elt + $(this).prop('tagName') + "_" + i;
                            $(this).attr('name', new_name);
                        }
                        else
                            new_name = "";
                    }

                    // nouvel rfrence pour l'attribut "for" d'un label qui fait rfrence  l'ancien id d'un input + "_" + numro de clonage
                    if (typeof($(this).attr('for')) != 'undefined'){
                        if (params.impact_for){
                            $(this).attr('for', $(this).attr('for') + "_" + i);
                        }
                    }

                    // Sauvegarde de ce nouvel enfant dans la liste de tous les lments clons depuis le dbut
                    if (typeof(doydoy_all_clones['"' + i + '"']['child']) == 'undefined'){
                        doydoy_all_clones['"' + i + '"']['child'] = [];
                    }
                    doydoy_all_clones['"' + i + '"']['child'][cpt_child] = {id        : new_id,
                                                                            id_before : id_before,
                                                                            num_clone : i,
                                                                            name      : new_name,
                                                                            elt       : $(this)};

                    // Sauvegarde de ce nouvel enfant dans la liste de tous les lments clons lors du dernier clonage
                    if (i == (doydoy_counter_clone - 1)){
                        doydoy_last_clones['child'][cpt_child] = {id        : new_id,
                                                                  id_before : id_before,
                                                                  num_clone : i,
                                                                  name      : new_name,
                                                                  elt       : $(this)};
                        /*
                        // fonction appele aprs la cration d'un nouvel enfant du dernier conteneur
                        if (params.each_last_child_callback != undefined){
                            params.each_last_child_callback('"' + i + '"', id_elt + "_" + i, cpt_child, new_id);
                        }
                        */
                    }

                    // fonction appele aprs la cration d'un nouveau conteneur
                    if (params.each_child_callback != undefined){
                        // paramtre 1 : "i"              correspond  l'index du conteneur -> doydoy_all_clones[i]                     -> commence  1 => Numro du clonage
                        // paramtre 2 : id_elt + "_" + i correspond  l'id du conteneur clon
                        // paramtre 3 : cpt_child        correspond  l'index de l'enfant  -> doydoy_all_clones[i]['child'][cpt_child] -> commence  0
                        // paramtre 4 : new_id           correspond  l'id de l'enfant clon
                        params.each_child_callback('"' + i + '"', id_elt + "_" + i, cpt_child, new_id);
                    }
                    // Incrmentation de l'enfant pour passer au suivant
                    cpt_child++;
                });

                // fonction appele aprs la cration d'un nouveau conteneur
                if (params.each_callback != undefined){
                    // paramtre 1 : "i" correspond  l'index du conteneur -> doydoy_all_clones[i] -> commence  1 => Numro du clonage
                    // paramtre 2 : id_elt + "_" + i correspond  l'id du conteneur clon
                    params.each_callback('"' + i + '"', id_elt + "_" + i);
                }
            }
            // R-initialisation du compteur de conteneurs (parents) crs
            doydoy_counter = doydoy_counter_clone - 1;
        });

        // fonction appele aprs la cration de tous les nouveaux conteneurs
        if (params.callback != undefined){
            params.callback();
        }

        // Permettre le chanage par jQuery
        return this;
    };
})(jQuery);
<commit_msg>Use JSLint<commit_after>/**
* Doydoy Clone
*
* @brief JQuery plugin to clone a group of elements with the management of ids
*
* @author doydoy44
* @version 1.1
*
*/

(function ($) {
    "use strict";
    /////////////////////////////////////////////////////
    // Variables globales au plugin mais prive        //
    // (non accessible en dehors du plugin)            //
    /////////////////////////////////////////////////////
    var
    // nbre de clonage pour viter d'avoir les mmes ids
        doydoy_counter = 0,
    // nouvel id du conteneur(parent) cr
        doydoy_new_id = null,
    // prfix d'un nouvel id au cas o l'id n'existerait pas
        glob_prefix_new_elt = "id_doydoy_clone_",
    // Liste de tous les lments cloner depuis le dbut
        doydoy_all_clones = [],
    // Liste de tous les lments cloner lors du dernier clonage
        doydoy_last_clones = [];

    //////////////////////////////////////////////////////////
    // LISTE DES FONCTIONS DISPONIBLES EN DEHORS DU CLONAGE //
    //////////////////////////////////////////////////////////
    // Rcupration du nombre de clonage effectu
    $.fn.doydoyGetCounter = function () {
        return doydoy_counter;
    };

    // Rcupration de la liste de tous les lments cloner depuis le dbut
    $.fn.doydoyGetAllClones = function () {
        return doydoy_all_clones;
    };

    // Rcupration de la liste de tous les lments cloner lors du dernier clonage
    $.fn.doydoyGetLastClones = function () {
        return doydoy_last_clones;
    };

    // Rcupration de l'id du dernier conteneur (parent) cr
    $.fn.doydoyGetLastNewId = function () {
        return doydoy_new_id;
    };

    // Affectation du prfix pour un nouvel id au cas o l'id n'existerait pas
    $.fn.doydoySetPrefixNewId = function (prefix_new_elt) {
        glob_prefix_new_elt = prefix_new_elt;
        return this;
    };

    // Rinitialisation de la liste de tous les lments cloner depuis le dbut
    $.fn.initAllClonesList = function () {
        doydoy_all_clones = [];
        return this;
    };

    /////////////////////////////////////////////////////
    // LISTE DES METHODES RACCOURCIES                  //
    /////////////////////////////////////////////////////
    // Mthode after pour le clonage
    $.fn.doydoyCloneAfter = function (params) {
        params = $.extend(params, {method : "after"});
        return this.doydoyClone(params);
    };
    // Mthode before pour le clonage
    $.fn.doydoyCloneBefore = function (params) {
        params = $.extend(params, {method : "before"});
        return this.doydoyClone(params);
    };
    // Mthode append pour le clonage
    $.fn.doydoyCloneAppend = function (params) {
        params = $.extend(params, {method : "append"});
        return this.doydoyClone(params);
    };
    // Mthode prepend pour le clonage
    $.fn.doydoyClonePrepend = function (params) {
        params = $.extend(params, {method : "prepend"});
        return this.doydoyClone(params);
    };

    /////////////////////////////////////////////////////
    // Plugin de clonage                               //
    /////////////////////////////////////////////////////
    $.fn.doydoyClone = function (params) {
        // type de traitement pour la fonction eval (after par dfaut)
        var function_plugin_name = 'after';

        // Fusionner les paramtres par dfaut et ceux de l'utilisateur
        params = $.extend({
            method         : "",
            target         : "",
            impact_name    : true,
            impact_for     : true,
            new_name       : false,
            new_all_name   : false,
            new_all_id     : false,
            prefix_new_elt : glob_prefix_new_elt
        }, params);

        if (params.new_all_name) {
            params.new_name = true;
        }

        // Incrmentation du compter pour commencer  avoir des id  partir de 1 (idfoo_1) et suprieur au dernier clonage
        doydoy_counter += 1;

        // Rcupration du type de traitement pour la fonction eval (after par dfaut)
        switch (params.method) {
        case "after":
        case "before":
        case "append":
        case "prepend":
            function_plugin_name = params.method;
            break;
        default:
            function_plugin_name = 'after';
            break;
        }

        // Traverser tous les nuds.
        this.each(function () {
            var
            // id sans le numro d'incrmentation du futur conteneur (parent)
                id_elt,
            // lment  cloner
                elt_a_cloner = this,
            // numro d'incrmentation du futur conteneur (parent)
                doydoy_counter_clone = doydoy_counter,
            // Rcupration de l'lment  qui rajouter les lments
                dernier_element = "",
            // Numro de l'enfant par rapport  son parent
                cpt_child = 0,
            // id d'origine de l'enfant avant son nouvel id
                id_before = "",
            // nouvel id de l'enfant
                new_id = "",
            // nouveau nom de l'enfant
                new_name = "",
            // compteur for
                cpt_for = "";

            // Initialisation des derniers lments clons
            doydoy_last_clones = [];

            // Initialisation du nouvel id
            doydoy_new_id = null;

            // Dfinition de l'id (sans le numro d'incrmentation) du futur conteneur (parent)
            if ($(this).attr('id') === undefined) {
                if ($(this).attr('name') !== undefined) {
                    id_elt = params.prefix_new_elt + $(this).attr('name');
                } else {
                    id_elt = params.prefix_new_elt + $(this).prop('tagName');
                }
            } else {
                id_elt = $(this).attr('id');
            }

            // Rcupration de l'lment  qui rajouter les lments clons et y affecter la mthode after, before, ...
            // si non renseign, on prend l'lment  cloner
            if (params.target !== "") {
                dernier_element = params.target;
            } else {
                dernier_element = $(this);
            }

            // Clonage de l'ensemble des lments
            function function_clone() {

                // retour de l'ensemble des lements clons
                return $(elt_a_cloner).clone(true).each(function () {
                    // Dtermination de l'd du parent clon
                    doydoy_new_id = id_elt + "_" + doydoy_counter_clone;

                    $(this).attr('id', doydoy_new_id);

                    // Dtermination du nouveau nom du parent clon si on a choisi l'option
                    var new_name_parent = "";
                    if ($(this).attr('name') !== undefined) {
                        new_name_parent = $(this).attr('name');
                        if (params.new_name || params.impact_name) {
                            new_name_parent += "_" + doydoy_counter_clone;
                            $(this).attr('name', new_name_parent);
                        }
                    } else {
                        if (params.new_name) {
                            new_name_parent = doydoy_new_id;
                            $(this).attr('name', new_name_parent);
                        }
                    }

                    // Changement de l'attribut for qui fait rfrence  l'ancien id d'un input + "_" + numro de clonage
                    if ($(this).attr('for') !== undefined) {
                        if (params.impact_for) {
                            $(this).attr('for', $(this).attr('for') + "_" + doydoy_counter_clone);
                        }
                    }

                    // Sauvegarde de ce nouveau parent dans la liste de tous les lments clons depuis le dbut
                    if (doydoy_all_clones['"' + doydoy_counter_clone + '"'] === undefined) {
                        doydoy_all_clones['"' + doydoy_counter_clone + '"'] = [];
                    }

                    doydoy_all_clones['"' + doydoy_counter_clone + '"'].parent = {id        : doydoy_new_id,
                                                                                id_before : id_elt,
                                                                                num_clone : doydoy_counter_clone,
                                                                                name      : new_name_parent,
                                                                                elt       : $(this)};
                    // Sauvegarde de ce nouveau parent dans la liste de tous les lments clons lors du dernier clonage
                    doydoy_last_clones.parent = {id        : doydoy_new_id,
                                                    id_before : id_elt,
                                                    num_clone : doydoy_counter_clone,
                                                    name      : new_name_parent,
                                                    elt       : $(this)};
                    // incrmentation du numro de clonage pour viter d'avoir les mmes ids
                    doydoy_counter_clone += 1;
                });
            }

            // parcourt de tous les enfants du conteneur cpt_for
            function each_child(cpt_for) {
                cpt_child = 0;

                $("#" + id_elt + "_" + cpt_for + " *").each(function () {
                    // Dtermination du nouvel id de l'enfant en cours
                    if ($(this).attr('id') !== undefined) {
                        // rcupration de l'id d'origine de l'enfant
                        id_before = $(this).attr('id');
                        new_id    = id_before + "_" + cpt_for;
                        // changement de l'id
                        $(this).attr('id', new_id);
                    } else {
                        // Initialisation de l'id d'origine et du nouvel id (car il n'en avait pas forcment)
                        id_before = "";
                        if (params.new_all_id) {
                            if ($(this).attr('name') !== undefined) {
                                new_id = params.prefix_new_elt + $(this).attr('name') + "_" + cpt_for;
                            } else {
                                new_id = params.prefix_new_elt + $(this).prop('tagName') + "_" + cpt_for;
                            }
                            // Changement de l'id
                            $(this).attr('id', new_id);
                        } else {
                            new_id = "";
                        }
                    }

                    // Changement du nom si on l'a demand (params.new_name : true)
                    if ($(this).attr('name') !== undefined) {
                        new_name = $(this).attr('name');
                        if (params.new_all_name || params.impact_name) {
                            new_name += "_" + cpt_for;
                            $(this).attr('name', new_name);
                        }
                    } else {
                        if (params.new_all_name) {
                            if (new_id !== "") {
                                new_name = new_id;
                            } else {
                                new_name = params.prefix_new_elt + $(this).prop('tagName') + "_" + cpt_for;
                            }
                            $(this).attr('name', new_name);
                        } else {
                            new_name = "";
                        }
                    }

                    // nouvel rfrence pour l'attribut "for" d'un label qui fait rfrence  l'ancien id d'un input + "_" + numro de clonage
                    if ($(this).attr('for') !== undefined) {
                        if (params.impact_for) {
                            $(this).attr('for', $(this).attr('for') + "_" + cpt_for);
                        }
                    }

                    // Sauvegarde de ce nouvel enfant dans la liste de tous les lments clons depuis le dbut
                    if (doydoy_all_clones['"' + cpt_for + '"'].child === undefined) {
                        doydoy_all_clones['"' + cpt_for + '"'].child = [];
                    }
                    doydoy_all_clones['"' + cpt_for + '"'].child[cpt_child] = {id        : new_id,
                                                                            id_before : id_before,
                                                                            num_clone : cpt_for,
                                                                            name      : new_name,
                                                                            elt       : $(this)};

                    // Sauvegarde de ce nouvel enfant dans la liste de tous les lments clons lors du dernier clonage
                    if (cpt_for === (doydoy_counter_clone - 1)) {
                        doydoy_last_clones.child[cpt_child] = {id        : new_id,
                                                                  id_before : id_before,
                                                                  num_clone : cpt_for,
                                                                  name      : new_name,
                                                                  elt       : $(this)};
                        /*
                        // fonction appele aprs la cration d'un nouvel enfant du dernier conteneur
                        if (params.each_last_child_callback != undefined){
                            params.each_last_child_callback('"' + cpt_for + '"', id_elt + "_" + cpt_for, cpt_child, new_id);
                        }
                        */
                    }

                    // fonction appele aprs la cration d'un nouveau conteneur
                    if (params.each_child_callback !== undefined) {
                        // paramtre 1 : "cpt_for"              correspond  l'index du conteneur -> doydoy_all_clones[cpt_for]                     -> commence  1 => Numro du clonage
                        // paramtre 2 : id_elt + "_" + cpt_for correspond  l'id du conteneur clon
                        // paramtre 3 : cpt_child        correspond  l'index de l'enfant  -> doydoy_all_clones[cpt_for]['child'][cpt_child] -> commence  0
                        // paramtre 4 : new_id           correspond  l'id de l'enfant clon
                        params.each_child_callback('"' + cpt_for + '"', id_elt + "_" + cpt_for, cpt_child, new_id);
                    }
                    // Incrmentation de l'enfant pour passer au suivant
                    cpt_child += 1;
                });

                // fonction appele aprs la cration d'un nouveau conteneur
                if (params.each_callback !== undefined) {
                    // paramtre 1 : "cpt_for" correspond  l'index du conteneur -> doydoy_all_clones[cpt_for] -> commence  1 => Numro du clonage
                    // paramtre 2 : id_elt + "_" + cpt_for correspond  l'id du conteneur clon
                    params.each_callback('"' + cpt_for + '"', id_elt + "_" + cpt_for);
                }
            }
            // Ajout de l'ensemble clon  l'lment choisi avec la mthode choisie (after, begin, prepend, append)
            //
            switch (function_plugin_name) {
            case "after":
                $(dernier_element).each(function () { $(this).after(function_clone()); });
                break;
            case "before":
                $(dernier_element).each(function () { $(this).before(function_clone()); });
                break;
            case "append":
                $(dernier_element).each(function () { $(this).append(function_clone()); });
                break;
            case "prepend":
                $(dernier_element).each(function () { $(this).prepend(function_clone()); });
                break;
            }
            // Initialisation de la liste des derniers enfants crs
            doydoy_last_clones.child = [];

            // R-attribution des ids des lements des conteneurs qui ont t crs
            for (cpt_for = doydoy_counter; cpt_for < doydoy_counter_clone; cpt_for += 1) {
                each_child(cpt_for);
            }
            // R-initialisation du compteur de conteneurs (parents) crs
            doydoy_counter = doydoy_counter_clone - 1;
        });

        // fonction appele aprs la cration de tous les nouveaux conteneurs
        if (params.callback !== undefined) {
            params.callback();
        }

        // Permettre le chanage par jQuery
        return this;
    };
})(jQuery);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { propType } from 'graphql-anywhere';
import styled from 'styled-components';
import { graphql } from 'react-apollo';

import myGroupLinksFragment from 'react/components/UserDropdown/components/MyGroupLinks/fragments/myGroupLinks';

import toggleMyGroupsDropdownVisibilityMutation from 'react/components/UserDropdown/components/MyGroupLinks/mutations/toggleMyGroupsDropdownVisibility';

import { overflowScrolling } from 'react/styles/mixins';

import Text from 'react/components/UI/Text';
import GenericButton from 'react/components/UI/GenericButton';
import Link from 'react/components/UserDropdown/components/Link';
import MyGroupLink from 'react/components/UserDropdown/components/MyGroupLinks/components/MyGroupLink';
import Modal from 'react/components/UI/Modal';
import CreateGroup from 'react/components/CreateGroup';

const Header = styled(Link)`
  position: relative;
  user-select: none;

  // Left-facing Caret
  &:after {
    display: block;
    content: '';
    position: absolute;
    top: 50%;
    right: 1em;
    width: 0;
    height: 0;
    transform: translateY(-50%);
    border-top: 0.25em solid transparent;
    border-left: 0.25em solid transparent;
    border-bottom: 0.25em solid transparent;
    border-right: 0.5em solid ${props => props.theme.colors.gray.regular};
    pointer-events: none;
  }

  ${props => !props.is_my_groups_dropdown_hidden && `
    &:after {
      border-top: 0.5em solid ${props.theme.colors.gray.regular};
      border-right: 0.25em solid transparent;
      border-bottom: 0;
      border-left: 0.25em solid transparent;
    }
  `}
`;

const BetaBadge = styled(Text).attrs({
  f: 0,
})`
  display: inline-block;
  color: ${props => props.theme.colors.gray.regular} !important;
  font-weight: normal;
  margin-left: 0.5em;

  &:before {
    content: '•';
    margin-right: 0.5em;
  }
`;

const Container = styled.div`
  margin-left: ${props => props.theme.space[3]};
  max-height: 30vmin;
  ${overflowScrolling}
`;

const LearnMoreLink = styled.a`
  font-weight: bold;
`;

class MyGroupLinks extends Component {
  static propTypes = {
    me: propType(myGroupLinksFragment).isRequired,
    toggleMyGroupsDropdownVisibility: PropTypes.func.isRequired,
  }

  toggle = (e) => {
    e.preventDefault();

    const { toggleMyGroupsDropdownVisibility, me } = this.props;
    const value = !me.is_my_groups_dropdown_hidden;

    return toggleMyGroupsDropdownVisibility({
      variables: {
        flags: [{
          name: 'is_my_groups_dropdown_hidden', value,
        }],
      },
      optimisticResponse: {
        __typename: 'Mutation',
        set_me_flags: {
          __typename: 'SetMeFlagsPayload',
          me: {
            ...me,
            is_my_groups_dropdown_hidden: value,
          },
        },
      },
    });
  }

  openCreateGroup = (e) => {
    e.preventDefault();

    const modal = new Modal(CreateGroup);
    modal.open();
  }

  render() {
    const { me: { groups, is_my_groups_dropdown_hidden } } = this.props;
    const hasGroups = groups.length > 0;

    return (
      <React.Fragment>

          Groups

          <BetaBadge>
            BETA
          </BetaBadge>

        {!is_my_groups_dropdown_hidden &&
          <React.Fragment>
            {groups.length === 0 &&
              <Text f={1} my="1rem" px="1rem" lineHeight={2}>
                Groups are a new way to collaborate on Are.na.

                <LearnMoreLink href="/getting-started-with-groups">Learn more</LearnMoreLink>
              </Text>
            }

            {groups.length > 0 &&
              <Container>
                {groups.map(group => (
                  <MyGroupLink key={`${group.__typename}_${group.id}`} group={group} />
                ))}
              </Container>
            }

            <GenericButton display="block" f={1} mt={5} mb={6} mx="1rem" onClick={this.openCreateGroup}>
              Create group
            </GenericButton>
          </React.Fragment>
        }
      </React.Fragment>
    );
  }
}

export default graphql(toggleMyGroupsDropdownVisibilityMutation, {
  name: 'toggleMyGroupsDropdownVisibility',
})(MyGroupLinks);
<commit_msg>Adds group icon<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { propType } from 'graphql-anywhere';
import styled from 'styled-components';
import { graphql } from 'react-apollo';

import myGroupLinksFragment from 'react/components/UserDropdown/components/MyGroupLinks/fragments/myGroupLinks';

import toggleMyGroupsDropdownVisibilityMutation from 'react/components/UserDropdown/components/MyGroupLinks/mutations/toggleMyGroupsDropdownVisibility';

import { overflowScrolling } from 'react/styles/mixins';

import Text from 'react/components/UI/Text';
import GenericButton from 'react/components/UI/GenericButton';
import Link from 'react/components/UserDropdown/components/Link';
import MyGroupLink from 'react/components/UserDropdown/components/MyGroupLinks/components/MyGroupLink';
import Modal from 'react/components/UI/Modal';
import CreateGroup from 'react/components/CreateGroup';
import Icons from 'react/components/UI/Icons';

const Header = styled(Link)`
  position: relative;
  user-select: none;

  // Left-facing Caret
  &:after {
    display: block;
    content: '';
    position: absolute;
    top: 50%;
    right: 1em;
    width: 0;
    height: 0;
    transform: translateY(-50%);
    border-top: 0.25em solid transparent;
    border-left: 0.25em solid transparent;
    border-bottom: 0.25em solid transparent;
    border-right: 0.5em solid ${props => props.theme.colors.gray.regular};
    pointer-events: none;
  }

  ${props => !props.is_my_groups_dropdown_hidden && `
    &:after {
      border-top: 0.5em solid ${props.theme.colors.gray.regular};
      border-right: 0.25em solid transparent;
      border-bottom: 0;
      border-left: 0.25em solid transparent;
    }
  `}
`;

const BetaBadge = styled(Text).attrs({
  f: 0,
})`
  display: inline-block;
  color: ${props => props.theme.colors.gray.regular} !important;
  font-weight: normal;
  margin-left: 0.5em;

  &:before {
    content: '•';
    margin-right: 0.5em;
  }
`;

const Container = styled.div`
  margin-left: ${props => props.theme.space[3]};
  max-height: 30vmin;
  ${overflowScrolling}
`;

const LearnMoreLink = styled.a`
  font-weight: bold;
`;

class MyGroupLinks extends Component {
  static propTypes = {
    me: propType(myGroupLinksFragment).isRequired,
    toggleMyGroupsDropdownVisibility: PropTypes.func.isRequired,
  }

  toggle = (e) => {
    e.preventDefault();

    const { toggleMyGroupsDropdownVisibility, me } = this.props;
    const value = !me.is_my_groups_dropdown_hidden;

    return toggleMyGroupsDropdownVisibility({
      variables: {
        flags: [{
          name: 'is_my_groups_dropdown_hidden', value,
        }],
      },
      optimisticResponse: {
        __typename: 'Mutation',
        set_me_flags: {
          __typename: 'SetMeFlagsPayload',
          me: {
            ...me,
            is_my_groups_dropdown_hidden: value,
          },
        },
      },
    });
  }

  openCreateGroup = (e) => {
    e.preventDefault();

    const modal = new Modal(CreateGroup);
    modal.open();
  }

  render() {
    const { me: { groups, is_my_groups_dropdown_hidden } } = this.props;
    const hasGroups = groups.length > 0;

    return (
      <React.Fragment>

          Groups

          <BetaBadge>
            BETA
          </BetaBadge>

        {!is_my_groups_dropdown_hidden &&
          <React.Fragment>
            {groups.length === 0 &&
              <Text f={1} my="1rem" px="1rem" lineHeight={2}>
                Groups are a new way to collaborate on Are.na.

                <LearnMoreLink href="/getting-started-with-groups">Learn more</LearnMoreLink>
              </Text>
            }

            {groups.length > 0 &&
              <Container>
                {groups.map(group => (
                  <MyGroupLink key={`${group.__typename}_${group.id}`} group={group} />
                ))}
              </Container>
            }

            <GenericButton display="block" f={1} mt={5} mb={6} mx="1rem" onClick={this.openCreateGroup}>
              <Icons name="Group" color="gray.medium" mr={4} />
              Create group
            </GenericButton>
          </React.Fragment>
        }
      </React.Fragment>
    );
  }
}

export default graphql(toggleMyGroupsDropdownVisibilityMutation, {
  name: 'toggleMyGroupsDropdownVisibility',
})(MyGroupLinks);
<|endoftext|>


<commit_before>/**
 * jQuery Geocoding and Places Autocomplete Plugin - V 1.5.0
 *
 * @author Martin Kleppe <kleppe@ubilabs.net>, 2012
 * @author Ubilabs http://ubilabs.net, 2012
 * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
 */

// # $.geocomplete()
// ## jQuery Geocoding and Places Autocomplete Plugin - V 1.5.0
//
// * https://github.com/ubilabs/geocomplete/
// * by Martin Kleppe <kleppe@ubilabs.net>

(function($, window, document, undefined){

  // ## Options
  // The default options for this plugin.
  //
  // * `map` - Might be a selector, an jQuery object or a DOM element. Default is `false` which shows no map.
  // * `details` - The container that should be populated with data. Defaults to `false` which ignores the setting.
  // * `location` - Location to initialize the map on. Might be an address `string` or an `array` with [latitude, longitude] or a `google.maps.LatLng`object. Default is `false` which shows a blank map.
  // * `bounds` - Whether to snap geocode search to map bounds. Default: `true` if false search globally. Alternatively pass a custom `LatLngBounds object.
  // * `autoselect` - Automatically selects the highlighted item or the first item from the suggestions list on Enter.
  // * `detailsAttribute` - The attribute's name to use as an indicator. Default: `"name"`
  // * `mapOptions` - Options to pass to the `google.maps.Map` constructor. See the full list [here](http://code.google.com/apis/maps/documentation/javascript/reference.html#MapOptions).
  // * `mapOptions.zoom` - The inital zoom level. Default: `14`
  // * `mapOptions.scrollwheel` - Whether to enable the scrollwheel to zoom the map. Default: `false`
  // * `mapOptions.mapTypeId` - The map type. Default: `"roadmap"`
  // * `markerOptions` - The options to pass to the `google.maps.Marker` constructor. See the full list [here](http://code.google.com/apis/maps/documentation/javascript/reference.html#MarkerOptions).
  // * `markerOptions.draggable` - If the marker is draggable. Default: `false`. Set to true to enable dragging.
  // * `markerOptions.disabled` - Do not show marker. Default: `false`. Set to true to disable marker.
  // * `maxZoom` - The maximum zoom level too zoom in after a geocoding response. Default: `16`
  // * `types` - An array containing one or more of the supported types for the places request. Default: `['geocode']` See the full list [here](http://code.google.com/apis/maps/documentation/javascript/places.html#place_search_requests).

  var defaults = {
    bounds: true,
    country: null,
    map: false,
    details: false,
    detailsAttribute: "name",
    autoselect: true,
    location: false,

    mapOptions: {
      zoom: 14,
      scrollwheel: false,
      mapTypeId: "roadmap"
    },

    markerOptions: {
      draggable: false
    },

    maxZoom: 16,
    types: ['geocode'],
    blur: false
  };

  // See: [Geocoding Types](https://developers.google.com/maps/documentation/geocoding/#Types)
  // on Google Developers.
  var componentTypes = ("street_address route intersection political " +
    "country administrative_area_level_1 administrative_area_level_2 " +
    "administrative_area_level_3 colloquial_area locality sublocality " +
    "neighborhood premise subpremise postal_code natural_feature airport " +
    "park point_of_interest post_box street_number floor room " +
    "lat lng viewport location " +
    "formatted_address location_type bounds").split(" ");

  // See: [Places Details Responses](https://developers.google.com/maps/documentation/javascript/places#place_details_responses)
  // on Google Developers.
  var placesDetails = ("id url website vicinity reference name rating " +
    "international_phone_number icon formatted_phone_number").split(" ");

  // The actual plugin constructor.
  function GeoComplete(input, options) {

    this.options = $.extend(true, {}, defaults, options);

    this.input = input;
    this.$input = $(input);

    this._defaults = defaults;
    this._name = 'geocomplete';

    this.init();
  }

  // Initialize all parts of the plugin.
  $.extend(GeoComplete.prototype, {
    init: function(){
      this.initMap();
      this.initMarker();
      this.initGeocoder();
      this.initDetails();
      this.initLocation();
    },

    // Initialize the map but only if the option `map` was set.
    // This will create a `map` within the given container
    // using the provided `mapOptions` or link to the existing map instance.
    initMap: function(){
      if (!this.options.map){ return; }

      if (typeof this.options.map.setCenter == "function"){
        this.map = this.options.map;
        return;
      }

      this.map = new google.maps.Map(
        $(this.options.map)[0],
        this.options.mapOptions
      );

      // add click event listener on the map
      google.maps.event.addListener(
        this.map,
        'click',
        $.proxy(this.mapClicked, this)
      );

      google.maps.event.addListener(
        this.map,
        'zoom_changed',
        $.proxy(this.mapZoomed, this)
      );
    },

    // Add a marker with the provided `markerOptions` but only
    // if the option was set. Additionally it listens for the `dragend` event
    // to notify the plugin about changes.
    initMarker: function(){
      if (!this.map){ return; }
      var options = $.extend(this.options.markerOptions, { map: this.map });

      if (options.disabled){ return; }

      this.marker = new google.maps.Marker(options);

      google.maps.event.addListener(
        this.marker,
        'dragend',
        $.proxy(this.markerDragged, this)
      );
    },

    // Associate the input with the autocompleter and create a geocoder
    // to fall back when the autocompleter does not return a value.
    initGeocoder: function(){

      var options = {
        types: this.options.types,
        bounds: this.options.bounds === true ? null : this.options.bounds,
        componentRestrictions: this.options.componentRestrictions
      };

      if (this.options.country){
        options.componentRestrictions = {country: this.options.country}
      }

      this.autocomplete = new google.maps.places.Autocomplete(
        this.input, options
      );

      this.geocoder = new google.maps.Geocoder();

      // Bind autocomplete to map bounds but only if there is a map
      // and `options.bindToMap` is set to true.
      if (this.map && this.options.bounds === true){
        this.autocomplete.bindTo('bounds', this.map);
      }

      // Watch `place_changed` events on the autocomplete input field.
      google.maps.event.addListener(
        this.autocomplete,
        'place_changed',
        $.proxy(this.placeChanged, this)
      );

      // Prevent parent form from being submitted if user hit enter.
      this.$input.keypress(function(event){
        if (event.keyCode === 13){ return false; }
      });

      // Listen for "geocode" events and trigger find action.
      this.$input.bind("geocode", $.proxy(function(){
        this.find();
      }, this));

      // Trigger find action when input element is blured out.
      // (Usefull for typing partial location and tabing to the next field
      // or clicking somewhere else.)
      if (this.options.blur === true){
        this.$input.blur($.proxy(function(){
          this.find();
        }, this));
      }
    },

    // Prepare a given DOM structure to be populated when we got some data.
    // This will cycle through the list of component types and map the
    // corresponding elements.
    initDetails: function(){
      if (!this.options.details){ return; }

      var $details = $(this.options.details),
        attribute = this.options.detailsAttribute,
        details = {};

      function setDetail(value){
        details[value] = $details.find("[" +  attribute + "=" + value + "]");
      }

      $.each(componentTypes, function(index, key){
        setDetail(key);
        setDetail(key + "_short");
      });

      $.each(placesDetails, function(index, key){
        setDetail(key);
      });

      this.$details = $details;
      this.details = details;
    },

    // Set the initial location of the plugin if the `location` options was set.
    // This method will care about converting the value into the right format.
    initLocation: function() {

      var location = this.options.location, latLng;

      if (!location) { return; }

      if (typeof location == 'string') {
        this.find(location);
        return;
      }

      if (location instanceof Array) {
        latLng = new google.maps.LatLng(location[0], location[1]);
      }

      if (location instanceof google.maps.LatLng){
        latLng = location;
      }

      if (latLng){
        if (this.map){ this.map.setCenter(latLng); }
        if (this.marker){ this.marker.setPosition(latLng); }
      }
    },

    // Look up a given address. If no `address` was specified it uses
    // the current value of the input.
    find: function(address){
      this.geocode({
        address: address || this.$input.val()
      });
    },

    // Requests details about a given location.
    // Additionally it will bias the requests to the provided bounds.
    geocode: function(request){
      if (this.options.bounds && !request.bounds){
        if (this.options.bounds === true){
          request.bounds = this.map && this.map.getBounds();
        } else {
          request.bounds = this.options.bounds;
        }
      }

      if (this.options.country){
        request.region = this.options.country;
      }

      this.geocoder.geocode(request, $.proxy(this.handleGeocode, this));
    },

    // Get the selected result. If no result is selected on the list, then get
    // the first result from the list.
    selectFirstResult: function() {
      //$(".pac-container").hide();

      var selected = '';
      // Check if any result is selected.
      if ($(".pac-item-selected")['0']) {
        selected = '-selected';
      }

      // Get the first suggestion's text.
      var $span1 = $(".pac-container .pac-item" + selected + ":first span:nth-child(2)").text();
      var $span2 = $(".pac-container .pac-item" + selected + ":first span:nth-child(3)").text();

      // Adds the additional information, if available.
      var firstResult = $span1;
      if ($span2) {
        firstResult += " - " + $span2;
      }

      this.$input.val(firstResult);

      return firstResult;
    },

    // Handles the geocode response. If more than one results was found
    // it triggers the "geocode:multiple" events. If there was an error
    // the "geocode:error" event is fired.
    handleGeocode: function(results, status){
      if (status === google.maps.GeocoderStatus.OK) {
        var result = results[0];
        this.$input.val(result.formatted_address);
        this.update(result);

        if (results.length > 1){
          this.trigger("geocode:multiple", results);
        }

      } else {
        this.trigger("geocode:error", status);
      }
    },

    // Triggers a given `event` with optional `arguments` on the input.
    trigger: function(event, argument){
      this.$input.trigger(event, [argument]);
    },

    // Set the map to a new center by passing a `geometry`.
    // If the geometry has a viewport, the map zooms out to fit the bounds.
    // Additionally it updates the marker position.
    center: function(geometry){

      if (geometry.viewport){
        this.map.fitBounds(geometry.viewport);
        if (this.map.getZoom() > this.options.maxZoom){
          this.map.setZoom(this.options.maxZoom);
        }
      } else {
        this.map.setZoom(this.options.maxZoom);
        this.map.setCenter(geometry.location);
      }

      if (this.marker){
        this.marker.setPosition(geometry.location);
        this.marker.setAnimation(this.options.markerOptions.animation);
      }
    },

    // Update the elements based on a single places or geoocoding response
    // and trigger the "geocode:result" event on the input.
    update: function(result){

      if (this.map){
        this.center(result.geometry);
      }

      if (this.$details){
        this.fillDetails(result);
      }

      this.trigger("geocode:result", result);
    },

    // Populate the provided elements with new `result` data.
    // This will lookup all elements that has an attribute with the given
    // component type.
    fillDetails: function(result){

      var data = {},
        geometry = result.geometry,
        viewport = geometry.viewport,
        bounds = geometry.bounds;

      // Create a simplified version of the address components.
      $.each(result.address_components, function(index, object){
        var name = object.types[0];
        data[name] = object.long_name;
        data[name + "_short"] = object.short_name;
      });

      // Add properties of the places details.
      $.each(placesDetails, function(index, key){
        data[key] = result[key];
      });

      // Add infos about the address and geometry.
      $.extend(data, {
        formatted_address: result.formatted_address,
        location_type: geometry.location_type || "PLACES",
        viewport: viewport,
        bounds: bounds,
        location: geometry.location,
        lat: geometry.location.lat(),
        lng: geometry.location.lng()
      });

      // Set the values for all details.
      $.each(this.details, $.proxy(function(key, $detail){
        var value = data[key];
        this.setDetail($detail, value);
      }, this));

      this.data = data;
    },

    // Assign a given `value` to a single `$element`.
    // If the element is an input, the value is set, otherwise it updates
    // the text content.
    setDetail: function($element, value){

      if (value === undefined){
        value = "";
      } else if (typeof value.toUrlValue == "function"){
        value = value.toUrlValue();
      }

      if ($element.is(":input")){
        $element.val(value);
      } else {
        $element.text(value);
      }
    },

    // Fire the "geocode:dragged" event and pass the new position.
    markerDragged: function(event){
      this.trigger("geocode:dragged", event.latLng);
    },

    mapClicked: function(event) {
        this.trigger("geocode:click", event.latLng);
    },

    mapZoomed: function(event) {
      this.trigger("geocode:zoom", this.map.getZoom());
    },

    // Restore the old position of the marker to the last now location.
    resetMarker: function(){
      this.marker.setPosition(this.data.location);
      this.setDetail(this.details.lat, this.data.location.lat());
      this.setDetail(this.details.lng, this.data.location.lng());
    },

    // Update the plugin after the user has selected an autocomplete entry.
    // If the place has no geometry it passes it to the geocoder.
    placeChanged: function(){
      var place = this.autocomplete.getPlace();

      if (!place.geometry){
        if (this.options.autoselect) {
          // Automatically selects the highlighted item or the first item from the
          // suggestions list.
          var autoSelection = this.selectFirstResult();
          this.find(autoSelection);
        }
      } else {
        // Use the input text if it already gives geometry.
        this.update(place);
      }
    }
  });

  // A plugin wrapper around the constructor.
  // Pass `options` with all settings that are different from the default.
  // The attribute is used to prevent multiple instantiations of the plugin.
  $.fn.geocomplete = function(options) {

    var attribute = 'plugin_geocomplete';

    // If you call `.geocomplete()` with a string as the first parameter
    // it returns the corresponding property or calls the method with the
    // following arguments.
    if (typeof options == "string"){

      var instance = $(this).data(attribute) || $(this).geocomplete().data(attribute),
        prop = instance[options];

      if (typeof prop == "function"){
        prop.apply(instance, Array.prototype.slice.call(arguments, 1));
        return $(this);
      } else {
        if (arguments.length == 2){
          prop = arguments[1];
        }
        return prop;
      }
    } else {
      return this.each(function() {
        // Prevent against multiple instantiations.
        var instance = $.data(this, attribute);
        if (!instance) {
          instance = new GeoComplete( this, options )
          $.data(this, attribute, instance);
        }
      });
    }
  };

})( jQuery, window, document );
<commit_msg>Avoid exception if getPlace() returns undefined<commit_after>/**
 * jQuery Geocoding and Places Autocomplete Plugin - V 1.5.0
 *
 * @author Martin Kleppe <kleppe@ubilabs.net>, 2012
 * @author Ubilabs http://ubilabs.net, 2012
 * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
 */

// # $.geocomplete()
// ## jQuery Geocoding and Places Autocomplete Plugin - V 1.5.0
//
// * https://github.com/ubilabs/geocomplete/
// * by Martin Kleppe <kleppe@ubilabs.net>

(function($, window, document, undefined){

  // ## Options
  // The default options for this plugin.
  //
  // * `map` - Might be a selector, an jQuery object or a DOM element. Default is `false` which shows no map.
  // * `details` - The container that should be populated with data. Defaults to `false` which ignores the setting.
  // * `location` - Location to initialize the map on. Might be an address `string` or an `array` with [latitude, longitude] or a `google.maps.LatLng`object. Default is `false` which shows a blank map.
  // * `bounds` - Whether to snap geocode search to map bounds. Default: `true` if false search globally. Alternatively pass a custom `LatLngBounds object.
  // * `autoselect` - Automatically selects the highlighted item or the first item from the suggestions list on Enter.
  // * `detailsAttribute` - The attribute's name to use as an indicator. Default: `"name"`
  // * `mapOptions` - Options to pass to the `google.maps.Map` constructor. See the full list [here](http://code.google.com/apis/maps/documentation/javascript/reference.html#MapOptions).
  // * `mapOptions.zoom` - The inital zoom level. Default: `14`
  // * `mapOptions.scrollwheel` - Whether to enable the scrollwheel to zoom the map. Default: `false`
  // * `mapOptions.mapTypeId` - The map type. Default: `"roadmap"`
  // * `markerOptions` - The options to pass to the `google.maps.Marker` constructor. See the full list [here](http://code.google.com/apis/maps/documentation/javascript/reference.html#MarkerOptions).
  // * `markerOptions.draggable` - If the marker is draggable. Default: `false`. Set to true to enable dragging.
  // * `markerOptions.disabled` - Do not show marker. Default: `false`. Set to true to disable marker.
  // * `maxZoom` - The maximum zoom level too zoom in after a geocoding response. Default: `16`
  // * `types` - An array containing one or more of the supported types for the places request. Default: `['geocode']` See the full list [here](http://code.google.com/apis/maps/documentation/javascript/places.html#place_search_requests).

  var defaults = {
    bounds: true,
    country: null,
    map: false,
    details: false,
    detailsAttribute: "name",
    autoselect: true,
    location: false,

    mapOptions: {
      zoom: 14,
      scrollwheel: false,
      mapTypeId: "roadmap"
    },

    markerOptions: {
      draggable: false
    },

    maxZoom: 16,
    types: ['geocode'],
    blur: false
  };

  // See: [Geocoding Types](https://developers.google.com/maps/documentation/geocoding/#Types)
  // on Google Developers.
  var componentTypes = ("street_address route intersection political " +
    "country administrative_area_level_1 administrative_area_level_2 " +
    "administrative_area_level_3 colloquial_area locality sublocality " +
    "neighborhood premise subpremise postal_code natural_feature airport " +
    "park point_of_interest post_box street_number floor room " +
    "lat lng viewport location " +
    "formatted_address location_type bounds").split(" ");

  // See: [Places Details Responses](https://developers.google.com/maps/documentation/javascript/places#place_details_responses)
  // on Google Developers.
  var placesDetails = ("id url website vicinity reference name rating " +
    "international_phone_number icon formatted_phone_number").split(" ");

  // The actual plugin constructor.
  function GeoComplete(input, options) {

    this.options = $.extend(true, {}, defaults, options);

    this.input = input;
    this.$input = $(input);

    this._defaults = defaults;
    this._name = 'geocomplete';

    this.init();
  }

  // Initialize all parts of the plugin.
  $.extend(GeoComplete.prototype, {
    init: function(){
      this.initMap();
      this.initMarker();
      this.initGeocoder();
      this.initDetails();
      this.initLocation();
    },

    // Initialize the map but only if the option `map` was set.
    // This will create a `map` within the given container
    // using the provided `mapOptions` or link to the existing map instance.
    initMap: function(){
      if (!this.options.map){ return; }

      if (typeof this.options.map.setCenter == "function"){
        this.map = this.options.map;
        return;
      }

      this.map = new google.maps.Map(
        $(this.options.map)[0],
        this.options.mapOptions
      );

      // add click event listener on the map
      google.maps.event.addListener(
        this.map,
        'click',
        $.proxy(this.mapClicked, this)
      );

      google.maps.event.addListener(
        this.map,
        'zoom_changed',
        $.proxy(this.mapZoomed, this)
      );
    },

    // Add a marker with the provided `markerOptions` but only
    // if the option was set. Additionally it listens for the `dragend` event
    // to notify the plugin about changes.
    initMarker: function(){
      if (!this.map){ return; }
      var options = $.extend(this.options.markerOptions, { map: this.map });

      if (options.disabled){ return; }

      this.marker = new google.maps.Marker(options);

      google.maps.event.addListener(
        this.marker,
        'dragend',
        $.proxy(this.markerDragged, this)
      );
    },

    // Associate the input with the autocompleter and create a geocoder
    // to fall back when the autocompleter does not return a value.
    initGeocoder: function(){

      var options = {
        types: this.options.types,
        bounds: this.options.bounds === true ? null : this.options.bounds,
        componentRestrictions: this.options.componentRestrictions
      };

      if (this.options.country){
        options.componentRestrictions = {country: this.options.country}
      }

      this.autocomplete = new google.maps.places.Autocomplete(
        this.input, options
      );

      this.geocoder = new google.maps.Geocoder();

      // Bind autocomplete to map bounds but only if there is a map
      // and `options.bindToMap` is set to true.
      if (this.map && this.options.bounds === true){
        this.autocomplete.bindTo('bounds', this.map);
      }

      // Watch `place_changed` events on the autocomplete input field.
      google.maps.event.addListener(
        this.autocomplete,
        'place_changed',
        $.proxy(this.placeChanged, this)
      );

      // Prevent parent form from being submitted if user hit enter.
      this.$input.keypress(function(event){
        if (event.keyCode === 13){ return false; }
      });

      // Listen for "geocode" events and trigger find action.
      this.$input.bind("geocode", $.proxy(function(){
        this.find();
      }, this));

      // Trigger find action when input element is blured out.
      // (Usefull for typing partial location and tabing to the next field
      // or clicking somewhere else.)
      if (this.options.blur === true){
        this.$input.blur($.proxy(function(){
          this.find();
        }, this));
      }
    },

    // Prepare a given DOM structure to be populated when we got some data.
    // This will cycle through the list of component types and map the
    // corresponding elements.
    initDetails: function(){
      if (!this.options.details){ return; }

      var $details = $(this.options.details),
        attribute = this.options.detailsAttribute,
        details = {};

      function setDetail(value){
        details[value] = $details.find("[" +  attribute + "=" + value + "]");
      }

      $.each(componentTypes, function(index, key){
        setDetail(key);
        setDetail(key + "_short");
      });

      $.each(placesDetails, function(index, key){
        setDetail(key);
      });

      this.$details = $details;
      this.details = details;
    },

    // Set the initial location of the plugin if the `location` options was set.
    // This method will care about converting the value into the right format.
    initLocation: function() {

      var location = this.options.location, latLng;

      if (!location) { return; }

      if (typeof location == 'string') {
        this.find(location);
        return;
      }

      if (location instanceof Array) {
        latLng = new google.maps.LatLng(location[0], location[1]);
      }

      if (location instanceof google.maps.LatLng){
        latLng = location;
      }

      if (latLng){
        if (this.map){ this.map.setCenter(latLng); }
        if (this.marker){ this.marker.setPosition(latLng); }
      }
    },

    // Look up a given address. If no `address` was specified it uses
    // the current value of the input.
    find: function(address){
      this.geocode({
        address: address || this.$input.val()
      });
    },

    // Requests details about a given location.
    // Additionally it will bias the requests to the provided bounds.
    geocode: function(request){
      if (this.options.bounds && !request.bounds){
        if (this.options.bounds === true){
          request.bounds = this.map && this.map.getBounds();
        } else {
          request.bounds = this.options.bounds;
        }
      }

      if (this.options.country){
        request.region = this.options.country;
      }

      this.geocoder.geocode(request, $.proxy(this.handleGeocode, this));
    },

    // Get the selected result. If no result is selected on the list, then get
    // the first result from the list.
    selectFirstResult: function() {
      //$(".pac-container").hide();

      var selected = '';
      // Check if any result is selected.
      if ($(".pac-item-selected")['0']) {
        selected = '-selected';
      }

      // Get the first suggestion's text.
      var $span1 = $(".pac-container .pac-item" + selected + ":first span:nth-child(2)").text();
      var $span2 = $(".pac-container .pac-item" + selected + ":first span:nth-child(3)").text();

      // Adds the additional information, if available.
      var firstResult = $span1;
      if ($span2) {
        firstResult += " - " + $span2;
      }

      this.$input.val(firstResult);

      return firstResult;
    },

    // Handles the geocode response. If more than one results was found
    // it triggers the "geocode:multiple" events. If there was an error
    // the "geocode:error" event is fired.
    handleGeocode: function(results, status){
      if (status === google.maps.GeocoderStatus.OK) {
        var result = results[0];
        this.$input.val(result.formatted_address);
        this.update(result);

        if (results.length > 1){
          this.trigger("geocode:multiple", results);
        }

      } else {
        this.trigger("geocode:error", status);
      }
    },

    // Triggers a given `event` with optional `arguments` on the input.
    trigger: function(event, argument){
      this.$input.trigger(event, [argument]);
    },

    // Set the map to a new center by passing a `geometry`.
    // If the geometry has a viewport, the map zooms out to fit the bounds.
    // Additionally it updates the marker position.
    center: function(geometry){

      if (geometry.viewport){
        this.map.fitBounds(geometry.viewport);
        if (this.map.getZoom() > this.options.maxZoom){
          this.map.setZoom(this.options.maxZoom);
        }
      } else {
        this.map.setZoom(this.options.maxZoom);
        this.map.setCenter(geometry.location);
      }

      if (this.marker){
        this.marker.setPosition(geometry.location);
        this.marker.setAnimation(this.options.markerOptions.animation);
      }
    },

    // Update the elements based on a single places or geoocoding response
    // and trigger the "geocode:result" event on the input.
    update: function(result){

      if (this.map){
        this.center(result.geometry);
      }

      if (this.$details){
        this.fillDetails(result);
      }

      this.trigger("geocode:result", result);
    },

    // Populate the provided elements with new `result` data.
    // This will lookup all elements that has an attribute with the given
    // component type.
    fillDetails: function(result){

      var data = {},
        geometry = result.geometry,
        viewport = geometry.viewport,
        bounds = geometry.bounds;

      // Create a simplified version of the address components.
      $.each(result.address_components, function(index, object){
        var name = object.types[0];
        data[name] = object.long_name;
        data[name + "_short"] = object.short_name;
      });

      // Add properties of the places details.
      $.each(placesDetails, function(index, key){
        data[key] = result[key];
      });

      // Add infos about the address and geometry.
      $.extend(data, {
        formatted_address: result.formatted_address,
        location_type: geometry.location_type || "PLACES",
        viewport: viewport,
        bounds: bounds,
        location: geometry.location,
        lat: geometry.location.lat(),
        lng: geometry.location.lng()
      });

      // Set the values for all details.
      $.each(this.details, $.proxy(function(key, $detail){
        var value = data[key];
        this.setDetail($detail, value);
      }, this));

      this.data = data;
    },

    // Assign a given `value` to a single `$element`.
    // If the element is an input, the value is set, otherwise it updates
    // the text content.
    setDetail: function($element, value){

      if (value === undefined){
        value = "";
      } else if (typeof value.toUrlValue == "function"){
        value = value.toUrlValue();
      }

      if ($element.is(":input")){
        $element.val(value);
      } else {
        $element.text(value);
      }
    },

    // Fire the "geocode:dragged" event and pass the new position.
    markerDragged: function(event){
      this.trigger("geocode:dragged", event.latLng);
    },

    mapClicked: function(event) {
        this.trigger("geocode:click", event.latLng);
    },

    mapZoomed: function(event) {
      this.trigger("geocode:zoom", this.map.getZoom());
    },

    // Restore the old position of the marker to the last now location.
    resetMarker: function(){
      this.marker.setPosition(this.data.location);
      this.setDetail(this.details.lat, this.data.location.lat());
      this.setDetail(this.details.lng, this.data.location.lng());
    },

    // Update the plugin after the user has selected an autocomplete entry.
    // If the place has no geometry it passes it to the geocoder.
    placeChanged: function(){
      var place = this.autocomplete.getPlace();

      if (!place || !place.geometry){
        if (this.options.autoselect) {
          // Automatically selects the highlighted item or the first item from the
          // suggestions list.
          var autoSelection = this.selectFirstResult();
          this.find(autoSelection);
        }
      } else {
        // Use the input text if it already gives geometry.
        this.update(place);
      }
    }
  });

  // A plugin wrapper around the constructor.
  // Pass `options` with all settings that are different from the default.
  // The attribute is used to prevent multiple instantiations of the plugin.
  $.fn.geocomplete = function(options) {

    var attribute = 'plugin_geocomplete';

    // If you call `.geocomplete()` with a string as the first parameter
    // it returns the corresponding property or calls the method with the
    // following arguments.
    if (typeof options == "string"){

      var instance = $(this).data(attribute) || $(this).geocomplete().data(attribute),
        prop = instance[options];

      if (typeof prop == "function"){
        prop.apply(instance, Array.prototype.slice.call(arguments, 1));
        return $(this);
      } else {
        if (arguments.length == 2){
          prop = arguments[1];
        }
        return prop;
      }
    } else {
      return this.each(function() {
        // Prevent against multiple instantiations.
        var instance = $.data(this, attribute);
        if (!instance) {
          instance = new GeoComplete( this, options )
          $.data(this, attribute, instance);
        }
      });
    }
  };

})( jQuery, window, document );
<|endoftext|>


<commit_before>/**
 * jQuery if-else plugin
 *
 * Creates if(), else() and fi() methods that can be used in
 * a chain of methods on jQuery objects
 *
 * @author Vegard Løkken <vegard@headspin.no>
 * @copyright 2013
 * @version 0.4
 * @licence MIT
 */
;(function(e){var t=e();var n;e.fn["if"]=function(r){if(this===t){return e()}else{n=this;return!!r?n:t}};e.fn["elif"]=function(e){return this.else().if(e)};e.fn["else"]=function(){return this===t?n||this:t};e.fn["fi"]=function(){return n||this}})(jQuery);
<commit_msg>Forgot to update the minified version.<commit_after>/**
 * jQuery if-else plugin
 *
 * Creates if(), else(), elif() and fi() methods that can be used in
 * a chain of methods on jQuery objects
 *
 * @author Vegard Løkken <vegard@headspin.no>
 * @copyright 2013
 * @version 0.5.0
 * @licence MIT
 */
;(function(e){var t=e();var n;e.fn["if"]=function(r){if(this===t){return e()}else{n=this;return!!r?n:t}};e.fn["elif"]=function(e){return this.else().if(e)};e.fn["else"]=function(){return this===t||this.prevObject===t?n||this:t};e.fn["fi"]=function(){return n||this}})(jQuery);
<|endoftext|>


<commit_before>/**
 * Image Slider
 *
 * @category    jQuery Plugin
 * @license     http://www.opensource.org/licenses/mit-license.html  MIT License
 * @copyright   2014 Daiki Sato
 * @author      Daiki Sato <sato.dik@gmail.com>
 * @link        http://orememo-v2.tumblr.com/
 * @version     1.0.0
 * @since       2014.05.16
 */

;(function($, window, document, undefined) {

	var pluginName = 'imageslider',
			defaults = {
				slideItems: '.is-item',
				slideContainer: '.is-container',
				slideDistance: 1,
				slideDuration: 1,
				slideEasing: 'linear',
				resizable: false,
				reverse: false
			};

	function Plugin(element, options) {
		var self = this;

		self.element = element;
		self.settings = $.extend({}, defaults, options);
		self._defaults = defaults;
		self._name = pluginName;

		$(window).on('load', function() { self.init(); });
		// this.init();
	}

	Plugin.prototype.init = function() {
		var self = this;

		self.$element = $(self.element);
		self.$slideContainer = self.$element.find(self.settings.slideContainer);
		self.$slideItems = self.$element.find(self.settings.slideItems);
		self.elementW = self.$element.width();
		self.slideContainerW = calcContainerSize(self.$slideContainer, self.$slideItems);
		self.slideItemsLength = self.$slideItems.length;

		self.$slideContainer.width(self.slideContainerW);
		self.$element.css('overflow', 'hidden');

		if(self.settings.resizable) {
			$(window).on('resize', function(){ self.resizeContainer(); });
		}

		self.resizeContainer();
		// self.startSlide();
	}
	Plugin.prototype.startSlide = function() {
		var self = this,
				$slideItemFirst = self.$slideContainer.find(self.settings.slideItems).eq(0),
				$slideItemLast = self.$slideContainer.find(self.settings.slideItems).eq(self.slideItemsLength - 1),
				slideItemFirstW = $slideItemFirst.width(),
				slideItemLastW = $slideItemLast.width();

		if($slideItemFirst.is(':animated')) return false;

		if(!self.settings.reverse) {
			// 右->左にスライドする
			$slideItemFirst.animate({
				marginLeft: parseInt($slideItemFirst.css('margin-left'), 10) - self.settings.slideDistance
			}, self.settings.slideDuration, self.settings.slideEasing, function() {
				if(Math.abs(parseInt($slideItemFirst.css('margin-left'), 10)) > slideItemFirstW) {
					$slideItemFirst.appendTo(self.$slideContainer).css('margin-left', 0);
				}
				self.startSlide();
			});
		} else {
			// 左->右にスライドする
			if(parseInt($slideItemFirst.css('margin-left'), 10) >= 0) {
				$slideItemLast.prependTo(self.$slideContainer).css('margin-left', -slideItemLastW);
				self.startSlide();
				return false;
			}

			$slideItemFirst.animate({
				marginLeft: parseInt($slideItemFirst.css('margin-left'), 10) + self.settings.slideDistance
			}, self.settings.slideDuration, self.settings.slideEasing, function() {
				self.startSlide();
			});
		}
	}
	Plugin.prototype.stopSlide = function() {
		var self = this;

		self.$slideItems.stop();
	}
	Plugin.prototype.resizeContainer = function() {
		var self = this,
				elementW = self.$element.width(),
				itemsW = self.slideContainerW;

		// self.$slideContainerの横幅がself.$elementの横幅より小さい時、スライドする要素をコピー
		// if(elementW < self.slideContainerW) return false;

		// スライドを一旦ストップ
		self.stopSlide();

		// self.$elementの横幅を超えるまでスライドする要素をコピーする
		adjustItemsLength(self.$slideContainer, self.$slideItems, elementW, itemsW);

		// 各種要素更新
		self.$slideItems = self.$element.find(self.settings.slideItems);
		self.slideContainerW = calcContainerSize(self.$slideContainer, self.$slideItems);
		self.elementW = elementW;
		self.$slideContainer.width(self.slideContainerW);
		self.slideItemsLength = self.$slideItems.length;

		// スライドを再スタートする
		self.startSlide();
	}

	function adjustItemsLength($container, $items, elementW, itemsW) {
		$items.each(function() {
			if(itemsW > elementW * 2) return false;

			var $clone = $(this).clone().css('margin-left', 0);

			$clone.appendTo($container);
			itemsW += $clone.width();
		});
	} // end of adjustItemsLength

	// 親要素のサイズを設定
	function calcContainerSize($container, $items) {
		var containerW = $container.width(),
				resultW = 0;

		$items.each(function() {
			resultW += $(this).width();
		});

		return resultW;
	} // end of calcContainerSize()

	$.fn[pluginName] = function(options) {
		this.each(function() {
			if(!$.data(this, 'plugin_' + pluginName)) {
				$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
			}
		});

		return this;
	}

})(jQuery, window, document, undefined);<commit_msg>バージョン情報を1.1.0に更新<commit_after>/**
 * Image Slider
 *
 * @category    jQuery Plugin
 * @license     http://www.opensource.org/licenses/mit-license.html  MIT License
 * @copyright   2014 Daiki Sato
 * @author      Daiki Sato <sato.dik@gmail.com>
 * @link        http://orememo-v2.tumblr.com/
 * @version     1.1.0
 * @since       2014.05.16
 */

;(function($, window, document, undefined) {

	var pluginName = 'imageslider',
			defaults = {
				slideItems: '.is-item',
				slideContainer: '.is-container',
				slideDistance: 1,
				slideDuration: 1,
				slideEasing: 'linear',
				resizable: false,
				reverse: false
			};

	function Plugin(element, options) {
		var self = this;

		self.element = element;
		self.settings = $.extend({}, defaults, options);
		self._defaults = defaults;
		self._name = pluginName;

		$(window).on('load', function() { self.init(); });
		// this.init();
	}

	Plugin.prototype.init = function() {
		var self = this;

		self.$element = $(self.element);
		self.$slideContainer = self.$element.find(self.settings.slideContainer);
		self.$slideItems = self.$element.find(self.settings.slideItems);
		self.elementW = self.$element.width();
		self.slideContainerW = calcContainerSize(self.$slideContainer, self.$slideItems);
		self.slideItemsLength = self.$slideItems.length;

		self.$slideContainer.width(self.slideContainerW);
		self.$element.css('overflow', 'hidden');

		if(self.settings.resizable) {
			$(window).on('resize', function(){ self.resizeContainer(); });
		}

		self.resizeContainer();
		// self.startSlide();
	}
	Plugin.prototype.startSlide = function() {
		var self = this,
				$slideItemFirst = self.$slideContainer.find(self.settings.slideItems).eq(0),
				$slideItemLast = self.$slideContainer.find(self.settings.slideItems).eq(self.slideItemsLength - 1),
				slideItemFirstW = $slideItemFirst.width(),
				slideItemLastW = $slideItemLast.width();

		if($slideItemFirst.is(':animated')) return false;

		if(!self.settings.reverse) {
			// 右->左にスライドする
			$slideItemFirst.animate({
				marginLeft: parseInt($slideItemFirst.css('margin-left'), 10) - self.settings.slideDistance
			}, self.settings.slideDuration, self.settings.slideEasing, function() {
				if(Math.abs(parseInt($slideItemFirst.css('margin-left'), 10)) > slideItemFirstW) {
					$slideItemFirst.appendTo(self.$slideContainer).css('margin-left', 0);
				}
				self.startSlide();
			});
		} else {
			// 左->右にスライドする
			if(parseInt($slideItemFirst.css('margin-left'), 10) >= 0) {
				$slideItemLast.prependTo(self.$slideContainer).css('margin-left', -slideItemLastW);
				self.startSlide();
				return false;
			}

			$slideItemFirst.animate({
				marginLeft: parseInt($slideItemFirst.css('margin-left'), 10) + self.settings.slideDistance
			}, self.settings.slideDuration, self.settings.slideEasing, function() {
				self.startSlide();
			});
		}
	}
	Plugin.prototype.stopSlide = function() {
		var self = this;

		self.$slideItems.stop();
	}
	Plugin.prototype.resizeContainer = function() {
		var self = this,
				elementW = self.$element.width(),
				itemsW = self.slideContainerW;

		// self.$slideContainerの横幅がself.$elementの横幅より小さい時、スライドする要素をコピー
		// if(elementW < self.slideContainerW) return false;

		// スライドを一旦ストップ
		self.stopSlide();

		// self.$elementの横幅を超えるまでスライドする要素をコピーする
		adjustItemsLength(self.$slideContainer, self.$slideItems, elementW, itemsW);

		// 各種要素更新
		self.$slideItems = self.$element.find(self.settings.slideItems);
		self.slideContainerW = calcContainerSize(self.$slideContainer, self.$slideItems);
		self.elementW = elementW;
		self.$slideContainer.width(self.slideContainerW);
		self.slideItemsLength = self.$slideItems.length;

		// スライドを再スタートする
		self.startSlide();
	}

	function adjustItemsLength($container, $items, elementW, itemsW) {
		$items.each(function() {
			if(itemsW > elementW * 2) return false;

			var $clone = $(this).clone().css('margin-left', 0);

			$clone.appendTo($container);
			itemsW += $clone.width();
		});
	} // end of adjustItemsLength

	// 親要素のサイズを設定
	function calcContainerSize($container, $items) {
		var containerW = $container.width(),
				resultW = 0;

		$items.each(function() {
			resultW += $(this).width();
		});

		return resultW;
	} // end of calcContainerSize()

	$.fn[pluginName] = function(options) {
		this.each(function() {
			if(!$.data(this, 'plugin_' + pluginName)) {
				$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
			}
		});

		return this;
	}

})(jQuery, window, document, undefined);<|endoftext|>


<commit_before>(function ($) {
    $.fn.longDialog = function (options) {
        var openButton = options.openButton,
            dialog = $(this);

        openButton.click(function (e) {
            dialog.fadeIn("fast", function () {
                $(this).attr("tabindex", "-1").focus();
            });
            e.preventDefault();
        });

        dialog.click(function () {
            $(this).fadeOut("fast", function () {
                $(this).attr("tabindex", "");
            });
        });

        dialog.find(".dialog").click(function (e) {
            e.stopPropagation();
        });
    };
})(jQuery);

<commit_msg>New approach. Need to be fihished.<commit_after>(function ($) {
    $.fn.longDialog = function (options) {
        var openButton = options.openButton,
            dialog = $(this),
            main = $(".main"),
            body = $("body"),
            html = $("html");

        openButton.click(function (e) {
            main.css("width", main.width() + "px");
            body.css("overflow", "hidden");
            var bst = body.scrollTop(),
                hst = html.scrollTop();
            dialog.css("top", bst !== 0 ? bst + "px" : (hst !== 0 ? hst + "px" : ""));
            dialog.fadeIn("fast", function () {
                //$(this).attr("tabindex", "-1").focus();
            });
            e.preventDefault();
        });

        dialog.click(function () {
            $(this).fadeOut("fast", function () {
                body.css("overflow", "");
                main.css("width", "");
                dialog.css("top", "");
                //$(this).attr("tabindex", "");
            });
        });

        dialog.find(".dialog").click(function (e) {
            e.stopPropagation();
        });
    };
})(jQuery);
<|endoftext|>


<commit_before>'use strict';

describe("Directives: Currency", function() {

  var element;
  var $scope;
  var form;

  beforeEach(module('mortgageCalculatorApp'));

  beforeEach(inject(function($compile, $rootScope){
    $scope = $rootScope;
    element = angular.element(
      '<form name="form">' +
        '<input type="text" name="annualIncome" ng-model="model.annualIncome" currency data-a-sign="£">' +
      '</form>'
    );
    $scope.model = { annualIncome: null};
    $compile(element)($scope);
    $scope.$digest();
    form = $scope.form;
  }));

  it('should be valid initially', function() {
      expect(form.annualIncome.$valid).toBe(true);
  });

  it('converts input values to integer types', function() {
    form.annualIncome.$setViewValue('£30,000.00');
    expect($scope.model.annualIncome).toEqual(30000);
    expect(form.annualIncome.$valid).toBe(true);
  });

});

<commit_msg>create a test for checking initial value of input when currency directive is used<commit_after>'use strict';

describe("Directives: Currency", function() {

  var element;
  var $scope;
  var form;

  beforeEach(module('mortgageCalculatorApp'));

  beforeEach(inject(function($compile, $rootScope){
    $scope = $rootScope;
    element = angular.element(
      '<form name="form">' +
        '<input type="text" name="annualIncome" ng-model="model.annualIncome" currency data-a-sign="£">' +
      '</form>'
    );
    $scope.model = { annualIncome: null};
    $compile(element)($scope);
    $scope.$digest();
    form = $scope.form;
  }));

  it('should be valid initially', function() {
    expect(form.annualIncome.$valid).toBe(true);
  });

  it('element should be initially empty', function() {
    expect(element.find('input').val()).toBe('');
  });

  it('sets the view value to the correct format', function() {
    form.annualIncome.$setViewValue('£30,000.00');
    expect(form.annualIncome.$viewValue).toBe('£30,000.00');
  });

  it('converts input values to integer types', function() {
    form.annualIncome.$setViewValue('£30,000.00');
    expect($scope.model.annualIncome).toEqual(30000);
    expect(form.annualIncome.$valid).toBe(true);
  });

});

<|endoftext|>


<commit_before>// Copyright 2018-2021, University of Colorado Boulder

/**
 * Creates an HBox that can have the sound toggle button, a11y button, or be empty
 *
 * @author Chris Klusendorf (PhET Interactive Simulations)
 */

import merge from '../../phet-core/js/merge.js';
import platform from '../../phet-core/js/platform.js';
import HBox from '../../scenery/js/nodes/HBox.js';
import joist from './joist.js';
import KeyboardHelpButton from './KeyboardHelpButton.js';
import NavigationBarSoundToggleButton from './NavigationBarSoundToggleButton.js';
import NavigationBarPreferencesButton from './preferences/NavigationBarPreferencesButton.js';

class A11yButtonsHBox extends HBox {

  /**
   * @param {Sim} sim
   * @param {Property.<Color|string>} backgroundColorProperty
   * @param {Tandem} tandem
   * @param {Object} [options]
   */
  constructor( sim, backgroundColorProperty, tandem, options ) {

    options = merge( {
      align: 'center',
      spacing: 6
    }, options );

    // list of optional buttons added for a11y
    const a11yButtons = [];

    if ( sim.preferencesConfiguration ) {
      const preferencesButton = new NavigationBarPreferencesButton(
        sim.preferencesConfiguration,
        sim.preferencesManager.preferencesProperties,
        sim.lookAndFeel,
        sim.allAudioEnabledProperty
      );

      a11yButtons.push( preferencesButton );
    }

    // If the sim has sound support in its API, then create the button. This is support consistent API for PhET-iO
    if ( sim.soundPartOfTheAPI ) {
      const soundOnOffButton = new NavigationBarSoundToggleButton(
        sim.allAudioEnabledProperty,
        backgroundColorProperty,
        tandem.createTandem( 'soundOnOffButton' )
      );

      // only put the sound on/off button on the nav bar if the sound library is enabled
      if ( sim.supportsSound ) {
        a11yButtons.push( soundOnOffButton );
      }
    }

    // Create the KeyboardHelpButton if there is content and the sim has supports Interactive Description. When running
    // in phet-io brand, the button is only created if accessibility is part of the permanent API in order to support
    // a consistent PhET-iO API.
    if ( sim.hasKeyboardHelpContent && ( phet.chipper.brand === 'phet-io' ? sim.accessibilityPartOfTheAPI :
                                         phet.chipper.queryParameters.supportsInteractiveDescription ) ) {

      // Pops open a dialog with information about keyboard navigation
      const keyboardHelpButton = new KeyboardHelpButton(
        sim.screenProperty,
        backgroundColorProperty,
        tandem.createTandem( 'keyboardHelpButton' )
      );

      // only show the keyboard help button if the sim supports interactive description, there is keyboard help content,
      // and we are not in mobile safari
      if ( phet.chipper.queryParameters.supportsInteractiveDescription && !platform.mobileSafari ) {
        a11yButtons.push( keyboardHelpButton );
      }
    }

    assert && assert( !options.children, 'A11yButtonsHBox sets children' );
    options.children = a11yButtons;

    super( options );
  }
}

joist.register( 'A11yButtonsHBox', A11yButtonsHBox );
export default A11yButtonsHBox;<commit_msg>Initial commit for audioManager.js - moving Audio, Sound, and Voicing related flags and Properties out of Sim.js and into audioManager.js, see https://github.com/phetsims/joist/issues/724<commit_after>// Copyright 2018-2021, University of Colorado Boulder

/**
 * Creates an HBox that can have the sound toggle button, a11y button, or be empty
 *
 * @author Chris Klusendorf (PhET Interactive Simulations)
 */

import merge from '../../phet-core/js/merge.js';
import platform from '../../phet-core/js/platform.js';
import HBox from '../../scenery/js/nodes/HBox.js';
import audioManager from './audioManager.js';
import joist from './joist.js';
import KeyboardHelpButton from './KeyboardHelpButton.js';
import NavigationBarSoundToggleButton from './NavigationBarSoundToggleButton.js';
import NavigationBarPreferencesButton from './preferences/NavigationBarPreferencesButton.js';

class A11yButtonsHBox extends HBox {

  /**
   * @param {Sim} sim
   * @param {Property.<Color|string>} backgroundColorProperty
   * @param {Tandem} tandem
   * @param {Object} [options]
   */
  constructor( sim, backgroundColorProperty, tandem, options ) {

    options = merge( {
      align: 'center',
      spacing: 6
    }, options );

    // list of optional buttons added for a11y
    const a11yButtons = [];

    if ( sim.preferencesConfiguration ) {
      const preferencesButton = new NavigationBarPreferencesButton(
        sim.preferencesConfiguration,
        sim.preferencesManager.preferencesProperties,
        sim.lookAndFeel,
        audioManager.audioEnabledProperty
      );

      a11yButtons.push( preferencesButton );
    }

    // If the sim has sound support in its API, then create the button. This is support consistent API for PhET-iO
    if ( audioManager.soundPartOfTheAPI ) {
      const soundOnOffButton = new NavigationBarSoundToggleButton(
        audioManager.audioEnabledProperty,
        backgroundColorProperty,
        tandem.createTandem( 'soundOnOffButton' )
      );

      // only put the sound on/off button on the nav bar if the sound library is enabled
      if ( audioManager.supportsSound ) {
        a11yButtons.push( soundOnOffButton );
      }
    }

    // Create the KeyboardHelpButton if there is content and the sim has supports Interactive Description. When running
    // in phet-io brand, the button is only created if accessibility is part of the permanent API in order to support
    // a consistent PhET-iO API.
    if ( sim.hasKeyboardHelpContent && ( phet.chipper.brand === 'phet-io' ? sim.accessibilityPartOfTheAPI :
                                         phet.chipper.queryParameters.supportsInteractiveDescription ) ) {

      // Pops open a dialog with information about keyboard navigation
      const keyboardHelpButton = new KeyboardHelpButton(
        sim.screenProperty,
        backgroundColorProperty,
        tandem.createTandem( 'keyboardHelpButton' )
      );

      // only show the keyboard help button if the sim supports interactive description, there is keyboard help content,
      // and we are not in mobile safari
      if ( phet.chipper.queryParameters.supportsInteractiveDescription && !platform.mobileSafari ) {
        a11yButtons.push( keyboardHelpButton );
      }
    }

    assert && assert( !options.children, 'A11yButtonsHBox sets children' );
    options.children = a11yButtons;

    super( options );
  }
}

joist.register( 'A11yButtonsHBox', A11yButtonsHBox );
export default A11yButtonsHBox;<|endoftext|>


<commit_before>// Copyright 2016-2018, University of Colorado Boulder

/**
 * Convenience subtype of Property that constrains values to be true or false.
 * Truthy/falsy values are considered invalid.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var axon = require( 'AXON/axon' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Property = require( 'AXON/Property' );
  var PropertyIO = require( 'AXON/PropertyIO' );

  // phet-io modules
  var BooleanIO = require( 'ifphetio!PHET_IO/types/BooleanIO' );

  /**
   * @param {boolean} value - initial value
   * @param {Object} [options]
   * @constructor
   */
  function BooleanProperty( value, options ) {

    options = _.extend( {
      phetioType: PropertyIO( BooleanIO )
    }, options );

    // configure value validation options
    assert && assert( !options.valueType, 'valueType is set by BooleanProperty' );
    options.valueType = 'boolean';
    assert && assert( !options.isValidValue, 'isValidValue is not supported by BooleanProperty' );
    assert && assert( !options.validValues, 'validValues is not supported by BooleanProperty' );

    Property.call( this, value, options );
  }

  axon.register( 'BooleanProperty', BooleanProperty );

  return inherit( Property, BooleanProperty );
} );<commit_msg>Put assertions together and moved them to first thing in the constructor, see https://github.com/phetsims/axon/issues/172<commit_after>// Copyright 2016-2018, University of Colorado Boulder

/**
 * Convenience subtype of Property that constrains values to be true or false.
 * Truthy/falsy values are considered invalid.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var axon = require( 'AXON/axon' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Property = require( 'AXON/Property' );
  var PropertyIO = require( 'AXON/PropertyIO' );

  // phet-io modules
  var BooleanIO = require( 'ifphetio!PHET_IO/types/BooleanIO' );

  /**
   * @param {boolean} value - initial value
   * @param {Object} [options]
   * @constructor
   */
  function BooleanProperty( value, options ) {

    // configure value validation options
    assert && assert( !options.valueType, 'valueType is set by BooleanProperty' );
    assert && assert( !options.isValidValue, 'isValidValue is not supported by BooleanProperty' );
    assert && assert( !options.validValues, 'validValues is not supported by BooleanProperty' );

    options = _.extend( {
      phetioType: PropertyIO( BooleanIO )
    }, options );

    // BooleanProperty requires values to be primitive booleans
    options.valueType = 'boolean';

    Property.call( this, value, options );
  }

  axon.register( 'BooleanProperty', BooleanProperty );

  return inherit( Property, BooleanProperty );
} );<|endoftext|>