<commit_before>var assert = require('assert');

var Razorback = require('../index');

describe('Object Normalizer/Denormalizer', function () {

    describe('denormalize', function () {
        it('should collapse a simple object to itself', function () {
            var obj = {
                a: 'first',
                b: 'second'
            };

            var actual = new Razorback().denormalize(obj);

            assert.equal(obj.a, actual.a);
            assert.equal(obj.b, actual.b);
        });

        it('should turn a object with 2 levels into a 1 level', function () {
            var obj = {
                a: 'first',
                b: {
                    c1: 'second',
                    c2: 'third'
                }
            };

            var expected = {
                a: 'first',
                b_c1: 'second',
                b_c2: 'third'
            };

            var actual = new Razorback().denormalize(obj);

            assert.equal(expected.a, actual.a);
            assert.equal(expected.b_c1, actual.b_c1);
            assert.equal(expected.b_c2, actual.b_c2);

        });

        it('should turn a object with 4 levels into a 1 level', function () {
            var obj = {
                a: 'first',
                b: {
                    c1: 'second',
                    c2: {
                        d1: {
                            e1: 'third'
                        }
                    },
                    c3: 'fourth'
                }
            };

            var expected = {
                a: 'first',
                b_c1: 'second',
                b_c2_d1_e1: 'third',
                b_c3: 'fourth'
            };

            var actual = new Razorback().denormalize(obj);

            assert.equal(expected.a, actual.a);
            assert.equal(expected.b_c1, actual.b_c1);
            assert.equal(expected.b_c2_d1_e1, actual.b_c2_d1_e1);
            assert.equal(expected.b_c3, actual.b_c3);
        });

        it('should turn an object with an array into an array of flat objects',
            function () {
                var obj = {
                    a: 'first',
                    b: [
                        '1',
                        '2',
                        '3'
                    ]
                };

                var expected = {
                    a: 'first',
                    b_0: '1',
                    b_1: '2',
                    b_2: '3'
                };

                var actual = new Razorback().denormalize(obj);

                assert.equal(expected.a, actual.a);
                assert.equal(expected.b_0, actual.b_0);
                assert.equal(expected.b_1, actual.b_1);
                assert.equal(expected.b_2, actual.b_2);
            });

        it('should flatten the objects within arrays', function () {
            var obj = {
                a: 'first',
                b: [
                    {
                        c: 'second',
                        d: 'third'
                    },
                    {
                        c: 'fourth',
                        d: 'fifth'
                    }
                ]
            };

            var expected = {
                a: 'first',
                b_0_c: 'second',
                b_0_d: 'third',
                b_1_c: 'fourth',
                b_1_d: 'fifth'
            };

            var actual = new Razorback().denormalize(obj);

            assert.equal(expected.a, actual.a);
            assert.equal(expected.b_0_c, actual.b_0_c);
            assert.equal(expected.b_0_d, actual.b_0_d);
            assert.equal(expected.b_1_c, actual.b_1_c);
            assert.equal(expected.b_1_d, actual.b_1_d);
        });

        it('should flatten the objects within arrays within arrays',
            function () {
                var obj = {
                    a: 'first',
                    b: [
                        {
                            c: 'second',
                            d: [
                                'third',
                                'fourth'
                            ]
                        },
                        {
                            c: 'fifth',
                            d: [
                                'sixth',
                                'seventh'
                            ]
                        }
                    ]
                };

                var expected = {
                    a: 'first',
                    b_0_c: 'second',
                    b_0_d_0: 'third',
                    b_0_d_1: 'fourth',
                    b_1_c: 'fifth',
                    b_1_d_0: 'sixth',
                    b_1_d_1: 'seventh'
                };

                var actual = new Razorback().denormalize(obj);

                assert.equal(expected.a, actual.a);
                assert.equal(expected.b_0_c, actual.b_0_c);
                assert.equal(expected.b_0_d_0, actual.b_0_d_0);
                assert.equal(expected.b_0_d_1, actual.b_0_d_1);
                assert.equal(expected.b_1_c, actual.b_1_c);
                assert.equal(expected.b_1_d_0, actual.b_1_d_0);
                assert.equal(expected.b_1_d_1, actual.b_1_d_1);
            });

        it('should allow custom seperators', function () {
            var obj = {
                a: {
                    b: 'first'
                }
            };

            var expected = {
                'a&b': 'first'
            };

            var actual = new Razorback({seperator: '&'}).denormalize(obj);

            assert.equal(expected['a&b'], actual['a&b']);
        });

    });

    describe('normalize', function () {
        it('should transform a flat object into itself', function () {
            var obj = {
                a: 'first',
                b: 'second'
            };

            var actual = new Razorback().normalize(obj);

            assert.equal(obj.a, actual.a);
            assert.equal(obj.b, actual.b);
        });

        it('should transform a flat object into a 2 level object', function () {
            var obj = {
                a: 'zeroth',
                b_c: 'first',
                b_d: 'second'
            };

            var expected = {
                a: 'zeroth',
                b: {
                    c: 'first',
                    d: 'second'
                }
            };

            var actual = new Razorback().normalize(obj);

            assert.equal(expected.a, actual.a);
            assert.equal(expected.b.c, actual.b.c);
            assert.equal(expected.b.d, actual.b.d);
        });

        it('should transform a flat object into a 4 level object', function () {
            var obj = {
                a_b: 'zeroth',
                a_c_e: 'first',
                a_c_f_g: 'first and a half',
                d: 'second'
            };

            var expected = {
                a: {
                    b: 'zeroth',
                    c: {
                        e: 'first',
                        f: {
                            g: 'first and a half'
                        }
                    }
                },
                d: 'second'
            };

            var actual = new Razorback().normalize(obj);

            assert.equal(expected.a.b, actual.a.b);
            assert.equal(expected.a.c.e, actual.a.c.e);
            assert.equal(expected.a.c.f.g, actual.a.c.f.g);
            assert.equal(expected.d, actual.d);
        });

        it('should transform index objects back into arrays', function () {
            var obj = {
                a: 'first',
                b_0: 'second',
                b_1: 'third'
            };

            var expected = {
                a: 'first',
                b: [
                    'second',
                    'third'
                ]
            };

            var actual = new Razorback().normalize(obj);

            assert.equal(expected.a, actual.a);
            assert.equal(expected.b[0], actual.b[0]);
            assert.equal(expected.b[1], actual.b[1]);
            assert.equal(true, expected.b.constructor === Array);
            assert.equal(true, actual.b.constructor === Array);
        });
    });

    describe('custom mappings', function () {
        it('should allow custom mappings to flat objects', function () {
            var obj = {
                a: {
                    b: 'first'
                }
            };

            var expected = {
                custom: 'first'
            };

            var actual = new Razorback({
                mappings: [
                    {
                        from: 'a_b',
                        to: 'custom'
                    }
                ]
            }).denormalize(obj);

            assert.equal(expected['custom'], actual['custom']);
        });

        it('should allow custom mappings to normalized objects', function () {
            var expected = {
                a: {
                    b: 'first'
                }
            };

            var obj = {
                custom: 'first'
            };

            var actual = new Razorback({
                mappings: [
                    {
                        from: 'a_b',
                        to: 'custom'
                    }
                ]
            }).normalize(obj);

            assert.equal(expected.a.b, actual.a.b);
        });
    });

    describe('advanced array mappings', function () {

        it('should map objects with arrays to arrays of flat objects',
            function () {
                var expected = [
                    {
                        a: 'first',
                        b: 'array1'
                    },
                    {
                        a: 'first',
                        b: 'array2'
                    },
                    {
                        a: 'first',
                        b: 'array3'
                    }
                ];

                var actual = new Razorback({
                    useDynamicArrays: true
                }).denormalize({
                        a: 'first',
                        b: [
                            'array1',
                            'array2',
                            'array3'
                        ]
                    });

                assert.equal(3, actual.length);
                assert.equal(expected[0].a, actual[0].a);
                assert.equal(expected[0].b, actual[0].b);
                assert.equal(expected[1].a, actual[1].a);
                assert.equal(expected[1].b, actual[1].b);
                assert.equal(expected[2].a, actual[2].a);
                assert.equal(expected[2].b, actual[2].b);
            });

        it('should map arrays of flat objects to normalized ' + 'objects',
            function () {
                var expected = {
                    a: 'first',
                    b: [
                        'array1',
                        'array2',
                        'array3'
                    ]
                };

                var actual = new Razorback({
                    useDynamicArrays: true
                }).normalize([
                        {
                            a: 'first',
                            b: 'array1'
                        },
                        {
                            a: 'first',
                            b: 'array2'
                        },
                        {
                            a: 'first',
                            b: 'array3'
                        }
                    ]);

                assert.equal(3, actual.b.length);
                assert.equal(expected.a, actual.a);
                assert.equal(expected.b[0], actual.b[0]);
                assert.equal(expected.b[1], actual.b[1]);
                assert.equal(expected.b[2], actual.b[2]);
            });

        it('should map arrays of flat objects to normalized objects with ' +
            'multiple levels', function () {
            var expected = {
                a: {
                    b: 'first'
                },
                c: [
                    'array1',
                    'array2',
                    'array3'
                ]
            };

            var actual = new Razorback({
                useDynamicArrays: true
            }).normalize([
                    {
                        a_b: 'first',
                        c: 'array1'
                    },
                    {
                        a_b: 'first',
                        c: 'array2'
                    },
                    {
                        a_b: 'first',
                        c: 'array3'
                    }
                ]);

            assert.equal(3, actual.c.length);
            assert.equal(expected.a.b, actual.a.b);
            assert.equal(expected.c[0], actual.c[0]);
            assert.equal(expected.c[1], actual.c[1]);
            assert.equal(expected.c[2], actual.c[2]);
        });

        it('should map arrays of flat objects to normalized objects with ' +
            'multiple levels', function () {
            var expected = {
                a: {
                    b: 'first'
                },
                c: [
                    'array1',
                    'array2',
                    'array3'
                ]
            };

            var actual = new Razorback({
                useDynamicArrays: true
            }).normalize([
                    {
                        a_b: 'first',
                        c: 'array1'
                    },
                    {
                        a_b: 'first',
                        c: 'array2'
                    },
                    {
                        a_b: 'first',
                        c: 'array3'
                    }
                ]);

            assert.equal(expected.a.b, actual.a.b);
            assert.equal(expected.c[0], actual.c[0]);
            assert.equal(expected.c[1], actual.c[1]);
            assert.equal(expected.c[2], actual.c[2]);
        });

        it('should denormalize deep objects with multiple arrays', function () {
            var actual = new Razorback({useDynamicArrays: true}).denormalize({
                a: 'top',
                b: [
                    {
                        c: 'alpha',
                        d: [
                            'first',
                            'second',
                            'third'
                        ]
                    }, {
                        c: 'beta',
                        d: [
                            'fourth',
                            'fifth',
                            'sixth'
                        ]
                    }
                ]
            });

            var expected = [
                {
                    a: 'top',
                    b_c: 'alpha',
                    b_d: 'first'
                },
                {
                    a: 'top',
                    b_c: 'alpha',
                    b_d: 'second'
                },
                {
                    a: 'top',
                    b_c: 'alpha',
                    b_d: 'third'
                },
                {
                    a: 'top',
                    b_c: 'beta',
                    b_d: 'fourth'
                },
                {
                    a: 'top',
                    b_c: 'beta',
                    b_d: 'fifth'
                },
                {
                    a: 'top',
                    b_c: 'beta',
                    b_d: 'sixth'
                }
            ];

            assert.equal(6, actual.length);

            for (var i = 0; i < expected.length; i++) {
                assert.equal(expected[i].a, actual[i].a);
                assert.equal(expected[i].b_c, actual[i].b_c);
                assert.equal(expected[i].b_d, actual[i].b_d);
            }
        });
    });
});
<commit_msg>Updating test descriptions<commit_after>var assert = require('assert');

var Razorback = require('../index');

describe('Razorback', function () {

    describe('denormalize feature', function () {
        it('should collapse a simple object to itself', function () {
            var obj = {
                a: 'first',
                b: 'second'
            };

            var actual = new Razorback().denormalize(obj);

            assert.equal(obj.a, actual.a);
            assert.equal(obj.b, actual.b);
        });

        it('should turn a object with 2 levels into a 1 level', function () {
            var obj = {
                a: 'first',
                b: {
                    c1: 'second',
                    c2: 'third'
                }
            };

            var expected = {
                a: 'first',
                b_c1: 'second',
                b_c2: 'third'
            };

            var actual = new Razorback().denormalize(obj);

            assert.equal(expected.a, actual.a);
            assert.equal(expected.b_c1, actual.b_c1);
            assert.equal(expected.b_c2, actual.b_c2);

        });

        it('should turn a object with 4 levels into a 1 level', function () {
            var obj = {
                a: 'first',
                b: {
                    c1: 'second',
                    c2: {
                        d1: {
                            e1: 'third'
                        }
                    },
                    c3: 'fourth'
                }
            };

            var expected = {
                a: 'first',
                b_c1: 'second',
                b_c2_d1_e1: 'third',
                b_c3: 'fourth'
            };

            var actual = new Razorback().denormalize(obj);

            assert.equal(expected.a, actual.a);
            assert.equal(expected.b_c1, actual.b_c1);
            assert.equal(expected.b_c2_d1_e1, actual.b_c2_d1_e1);
            assert.equal(expected.b_c3, actual.b_c3);
        });

        it('should turn an object with an array into an array of flat objects',
            function () {
                var obj = {
                    a: 'first',
                    b: [
                        '1',
                        '2',
                        '3'
                    ]
                };

                var expected = {
                    a: 'first',
                    b_0: '1',
                    b_1: '2',
                    b_2: '3'
                };

                var actual = new Razorback().denormalize(obj);

                assert.equal(expected.a, actual.a);
                assert.equal(expected.b_0, actual.b_0);
                assert.equal(expected.b_1, actual.b_1);
                assert.equal(expected.b_2, actual.b_2);
            });

        it('should flatten the objects within arrays', function () {
            var obj = {
                a: 'first',
                b: [
                    {
                        c: 'second',
                        d: 'third'
                    },
                    {
                        c: 'fourth',
                        d: 'fifth'
                    }
                ]
            };

            var expected = {
                a: 'first',
                b_0_c: 'second',
                b_0_d: 'third',
                b_1_c: 'fourth',
                b_1_d: 'fifth'
            };

            var actual = new Razorback().denormalize(obj);

            assert.equal(expected.a, actual.a);
            assert.equal(expected.b_0_c, actual.b_0_c);
            assert.equal(expected.b_0_d, actual.b_0_d);
            assert.equal(expected.b_1_c, actual.b_1_c);
            assert.equal(expected.b_1_d, actual.b_1_d);
        });

        it('should flatten the objects within arrays within arrays',
            function () {
                var obj = {
                    a: 'first',
                    b: [
                        {
                            c: 'second',
                            d: [
                                'third',
                                'fourth'
                            ]
                        },
                        {
                            c: 'fifth',
                            d: [
                                'sixth',
                                'seventh'
                            ]
                        }
                    ]
                };

                var expected = {
                    a: 'first',
                    b_0_c: 'second',
                    b_0_d_0: 'third',
                    b_0_d_1: 'fourth',
                    b_1_c: 'fifth',
                    b_1_d_0: 'sixth',
                    b_1_d_1: 'seventh'
                };

                var actual = new Razorback().denormalize(obj);

                assert.equal(expected.a, actual.a);
                assert.equal(expected.b_0_c, actual.b_0_c);
                assert.equal(expected.b_0_d_0, actual.b_0_d_0);
                assert.equal(expected.b_0_d_1, actual.b_0_d_1);
                assert.equal(expected.b_1_c, actual.b_1_c);
                assert.equal(expected.b_1_d_0, actual.b_1_d_0);
                assert.equal(expected.b_1_d_1, actual.b_1_d_1);
            });

        it('should allow custom seperators', function () {
            var obj = {
                a: {
                    b: 'first'
                }
            };

            var expected = {
                'a&b': 'first'
            };

            var actual = new Razorback({seperator: '&'}).denormalize(obj);

            assert.equal(expected['a&b'], actual['a&b']);
        });

    });

    describe('normalize feature', function () {
        it('should transform a flat object into itself', function () {
            var obj = {
                a: 'first',
                b: 'second'
            };

            var actual = new Razorback().normalize(obj);

            assert.equal(obj.a, actual.a);
            assert.equal(obj.b, actual.b);
        });

        it('should transform a flat object into a 2 level object', function () {
            var obj = {
                a: 'zeroth',
                b_c: 'first',
                b_d: 'second'
            };

            var expected = {
                a: 'zeroth',
                b: {
                    c: 'first',
                    d: 'second'
                }
            };

            var actual = new Razorback().normalize(obj);

            assert.equal(expected.a, actual.a);
            assert.equal(expected.b.c, actual.b.c);
            assert.equal(expected.b.d, actual.b.d);
        });

        it('should transform a flat object into a 4 level object', function () {
            var obj = {
                a_b: 'zeroth',
                a_c_e: 'first',
                a_c_f_g: 'first and a half',
                d: 'second'
            };

            var expected = {
                a: {
                    b: 'zeroth',
                    c: {
                        e: 'first',
                        f: {
                            g: 'first and a half'
                        }
                    }
                },
                d: 'second'
            };

            var actual = new Razorback().normalize(obj);

            assert.equal(expected.a.b, actual.a.b);
            assert.equal(expected.a.c.e, actual.a.c.e);
            assert.equal(expected.a.c.f.g, actual.a.c.f.g);
            assert.equal(expected.d, actual.d);
        });

        it('should transform index objects back into arrays', function () {
            var obj = {
                a: 'first',
                b_0: 'second',
                b_1: 'third'
            };

            var expected = {
                a: 'first',
                b: [
                    'second',
                    'third'
                ]
            };

            var actual = new Razorback().normalize(obj);

            assert.equal(expected.a, actual.a);
            assert.equal(expected.b[0], actual.b[0]);
            assert.equal(expected.b[1], actual.b[1]);
            assert.equal(true, expected.b.constructor === Array);
            assert.equal(true, actual.b.constructor === Array);
        });
    });

    describe('custom mappings', function () {
        it('should allow custom mappings to flat objects', function () {
            var obj = {
                a: {
                    b: 'first'
                }
            };

            var expected = {
                custom: 'first'
            };

            var actual = new Razorback({
                mappings: [
                    {
                        from: 'a_b',
                        to: 'custom'
                    }
                ]
            }).denormalize(obj);

            assert.equal(expected['custom'], actual['custom']);
        });

        it('should allow custom mappings to normalized objects', function () {
            var expected = {
                a: {
                    b: 'first'
                }
            };

            var obj = {
                custom: 'first'
            };

            var actual = new Razorback({
                mappings: [
                    {
                        from: 'a_b',
                        to: 'custom'
                    }
                ]
            }).normalize(obj);

            assert.equal(expected.a.b, actual.a.b);
        });
    });

    describe('advanced array mappings', function () {
        it('should map objects with arrays to arrays of flat objects',
            function () {
                var expected = [
                    {
                        a: 'first',
                        b: 'array1'
                    },
                    {
                        a: 'first',
                        b: 'array2'
                    },
                    {
                        a: 'first',
                        b: 'array3'
                    }
                ];

                var actual = new Razorback({
                    useDynamicArrays: true
                }).denormalize({
                        a: 'first',
                        b: [
                            'array1',
                            'array2',
                            'array3'
                        ]
                    });

                assert.equal(3, actual.length);
                assert.equal(expected[0].a, actual[0].a);
                assert.equal(expected[0].b, actual[0].b);
                assert.equal(expected[1].a, actual[1].a);
                assert.equal(expected[1].b, actual[1].b);
                assert.equal(expected[2].a, actual[2].a);
                assert.equal(expected[2].b, actual[2].b);
            });

        it('should map arrays of flat objects to normalized ' + 'objects',
            function () {
                var expected = {
                    a: 'first',
                    b: [
                        'array1',
                        'array2',
                        'array3'
                    ]
                };

                var actual = new Razorback({
                    useDynamicArrays: true
                }).normalize([
                        {
                            a: 'first',
                            b: 'array1'
                        },
                        {
                            a: 'first',
                            b: 'array2'
                        },
                        {
                            a: 'first',
                            b: 'array3'
                        }
                    ]);

                assert.equal(3, actual.b.length);
                assert.equal(expected.a, actual.a);
                assert.equal(expected.b[0], actual.b[0]);
                assert.equal(expected.b[1], actual.b[1]);
                assert.equal(expected.b[2], actual.b[2]);
            });

        it('should map arrays of flat objects to normalized objects with ' +
            'multiple levels', function () {
            var expected = {
                a: {
                    b: 'first'
                },
                c: [
                    'array1',
                    'array2',
                    'array3'
                ]
            };

            var actual = new Razorback({
                useDynamicArrays: true
            }).normalize([
                    {
                        a_b: 'first',
                        c: 'array1'
                    },
                    {
                        a_b: 'first',
                        c: 'array2'
                    },
                    {
                        a_b: 'first',
                        c: 'array3'
                    }
                ]);

            assert.equal(3, actual.c.length);
            assert.equal(expected.a.b, actual.a.b);
            assert.equal(expected.c[0], actual.c[0]);
            assert.equal(expected.c[1], actual.c[1]);
            assert.equal(expected.c[2], actual.c[2]);
        });

        it('should map arrays of flat objects to normalized objects with ' +
            'multiple levels', function () {
            var expected = {
                a: {
                    b: 'first'
                },
                c: [
                    'array1',
                    'array2',
                    'array3'
                ]
            };

            var actual = new Razorback({
                useDynamicArrays: true
            }).normalize([
                    {
                        a_b: 'first',
                        c: 'array1'
                    },
                    {
                        a_b: 'first',
                        c: 'array2'
                    },
                    {
                        a_b: 'first',
                        c: 'array3'
                    }
                ]);

            assert.equal(expected.a.b, actual.a.b);
            assert.equal(expected.c[0], actual.c[0]);
            assert.equal(expected.c[1], actual.c[1]);
            assert.equal(expected.c[2], actual.c[2]);
        });

        it('should denormalize deep objects with multiple arrays', function () {
            var actual = new Razorback({useDynamicArrays: true}).denormalize({
                a: 'top',
                b: [
                    {
                        c: 'alpha',
                        d: [
                            'first',
                            'second',
                            'third'
                        ]
                    }, {
                        c: 'beta',
                        d: [
                            'fourth',
                            'fifth',
                            'sixth'
                        ]
                    }
                ]
            });

            var expected = [
                {
                    a: 'top',
                    b_c: 'alpha',
                    b_d: 'first'
                },
                {
                    a: 'top',
                    b_c: 'alpha',
                    b_d: 'second'
                },
                {
                    a: 'top',
                    b_c: 'alpha',
                    b_d: 'third'
                },
                {
                    a: 'top',
                    b_c: 'beta',
                    b_d: 'fourth'
                },
                {
                    a: 'top',
                    b_c: 'beta',
                    b_d: 'fifth'
                },
                {
                    a: 'top',
                    b_c: 'beta',
                    b_d: 'sixth'
                }
            ];

            assert.equal(6, actual.length);

            for (var i = 0; i < expected.length; i++) {
                assert.equal(expected[i].a, actual[i].a);
                assert.equal(expected[i].b_c, actual[i].b_c);
                assert.equal(expected[i].b_d, actual[i].b_d);
            }
        });
    });
});
<|endoftext|>


<commit_before>/*** MapView ***/
//NOTE: Mapview only renders the DOM once. From then on, it only renders inside the google map via api controls
var React = require('react');

var MapView = React.createClass({

  propTypes: {

  },

  defaultOptions: {

  },

  getInitialState () {
    return {
      displayedMarkers: []
    }
  }, //getInitialState()
  componentDidMount () {
    // console.log("MapView ---> inside componentDidMount");

    // QueryStore.addChangeListener(this._onChange)

  },

  componentDidUpdate(prevProps, prevState) {
    // console.log("MapView ---> inside componentDidUpdate ");
    // if(prevProps.currentRoute)
    // this.clearMapMarkers();
    // this.updateMapMarkers();
  },

  shouldComponentUpdate(prevProps, prevState) {
    var prevRoute = this.props.currentRoute;
    var newRoute = prevProps.currentRoute;
    if(prevRoute && newRoute){

      // console.log("************** prevProps = ", prevProps);
      // console.log("************** currentRoute = ", this.props.currentRoute);
      // if(prevProps.currentRoute.index !== this.props.currentRoute.index){
      // }
      if(prevRoute.index !== newRoute.index){
        console.log("************** New Route has been set");
        this.clearMapMarkers();
      }
    }else{ // currentRoute has changed
      this.clearMapMarkers();
    } //

    this.updateMapMarkers(newRoute.filteredVenues);

    return false;
  },

  //Gets the previous number of waypoints and the new number to be querried
  _onChange () {
    // this.clearMapMarkers();
    // this.updateMapMarkers(); //newVenuesArr
  },

  // Print new markers ()
  updateMapMarkers: function(newVenuesArr){
    // we are going to check markers array has already been printed
    // var newVenuesArr = this.props.currentRoute.filteredVenues;

    var map = window.map;
    var displayedMarkers = this.state.displayedMarkers; //array of
    var component = this;

    /**** remove unnecessary displayedMarkers ****/
    for(var venue_id in displayedMarkers){
      var marker = displayedMarkers[venue_id];

      var found = newVenuesArr.filter(function(venue){
        return venue_id === venue.id;
      });

      if(found.length===0){ //not found
        marker.setMap(null);
        delete displayedMarkers[venue_id]; //delete marker from displayed markers
      } //if

    };

    /**** print un ****/
    newVenuesArr.forEach(function(venue, index){

      var {lng, lat} = venue.location;

      //create new marker only if marker has not been displayed
      if(!displayedMarkers[venue.id]){ //
        var position = new google.maps.LatLng(lat, lng);

        var marker = new google.maps.Marker({
          position: position,
        });

        // create custom infowindow
        // NOTE: we can also add rating color to decorate marker
        var infowindow = new google.maps.InfoWindow({
          content: venue.name + "
 Rating: "+venue.rating
        });

        var markerIsActive = false;

        //create event listener to open info window
        google.maps.event.addListener(marker, 'mouseover', function() {
          if(!markerIsActive){
            infowindow.open(map, this);
          }
        }); //mouseover

        // create event listener to close info window
        google.maps.event.addListener(marker, 'mouseout', function() {
          if(!markerIsActive){
            infowindow.close();
          }
        }); //mouseout

        // create event listener to close info window
        google.maps.event.addListener(marker, 'click', function() {
          if(markerIsActive){ // deactivate this marker
            markerIsActive = false;
            infowindow.close();

          }else if(!markerIsActive){ //activate this marker
            markerIsActive = true;
            if(window.activeInfoWindow){
              window.activeInfoWindow.close(); //close previous
            }
            window.activeInfoWindow = infowindow; //update current;
          } //if
        }); //mouseout

        google.maps.event.addListener(marker, 'dblclick', function() {
          component.openFourSquare(venue); //load new page

        });

        //show map marker
        marker.setMap(map);
        // add current marker to state
        component.state.displayedMarkers[venue.id] = marker;
        // component.state.displayedMarkers.push(marker);
      } //if(marker)

      //display markers
    }); //forEach
  }, //updateMapMarkers()

  // // clear map markers
  // clearMapMarkers (){
  //   var markers = this.state.markers;

  //   for(var key in markers){
  //     var marker = markers[key];
  //     marker.setMap(null);
  //   } //for

  //   this.state.markers = {};
  // }, //clearMapMarkers

  // clear map markers
  clearMapMarkers (){
    var markers = this.state.markers;

    for(var key in markers){
      var marker = markers[key];
      marker.setMap(null);
    } //for

    this.state.markers = {};
  }, //clearMapMarkers

  render () {
    // var component = this;

    // var listDetails = VenueStore.getVenues().map(function(venue, index) {
    //   return (
    //     <VenueView venue={venue}/>
    //   )
    // });

    return (

    );
  }
});

module.exports = MapView;<commit_msg>for rebase<commit_after>/*** MapView ***/
//NOTE: Mapview only renders the DOM once. From then on, it only renders inside the google map via api controls
var React = require('react');

var MapView = React.createClass({

  propTypes: {

  },

  defaultOptions: {

  },

  getInitialState () {
    return {
      displayedMarkers: []
    }
  }, //getInitialState()
  componentDidMount () {
    // console.log("MapView ---> inside componentDidMount");

    // QueryStore.addChangeListener(this._onChange)

  },

  componentDidUpdate(prevProps, prevState) {
    // console.log("MapView ---> inside componentDidUpdate ");
    // if(prevProps.currentRoute)
    // this.clearMapMarkers();
    // this.updateMapMarkers();
  },

  shouldComponentUpdate(prevProps, prevState) {
    var prevRoute = this.props.currentRoute;
    var newRoute = prevProps.currentRoute;
    if(prevRoute && newRoute){

      // console.log("************** prevProps = ", prevProps);
      // console.log("************** currentRoute = ", this.props.currentRoute);
      // if(prevProps.currentRoute.index !== this.props.currentRoute.index){
      // }
      if(prevRoute.index !== newRoute.index){
        console.log("************** New Route has been set");
        this.clearMapMarkers();
      }
    }else{ // currentRoute has changed
      this.clearMapMarkers();
    } //

    this.updateMapMarkers(newRoute.filteredVenues);

    return false;
  },

  //Gets the previous number of waypoints and the new number to be querried
  _onChange () {
    // this.clearMapMarkers();
    // this.updateMapMarkers(); //newVenuesArr
  },

  // Print new markers ()
  updateMapMarkers: function(newVenuesArr){
    // we are going to check markers array has already been printed
    // var newVenuesArr = this.props.currentRoute.filteredVenues;

    var map = window.map;
    var displayedMarkers = this.state.displayedMarkers; //array of
    var component = this;

    /**** remove unnecessary displayedMarkers ****/
    for(var venue_id in displayedMarkers){
      var marker = displayedMarkers[venue_id];

      var found = newVenuesArr.filter(function(venue){
        return venue_id === venue.id;
      });

      if(found.length===0){ //not found
        marker.setMap(null);
        delete displayedMarkers[venue_id]; //delete marker from displayed markers
      } //if

    };

    /**** print un ****/
    newVenuesArr.forEach(function(venue, index){

      var {lng, lat} = venue.location;

      //create new marker only if marker has not been displayed
      if(!displayedMarkers[venue.id]){ //
        var position = new google.maps.LatLng(lat, lng);

        var marker = new google.maps.Marker({
          position: position,
        });

        // create custom infowindow
        // NOTE: we can also add rating color to decorate marker
        var infowindow = new google.maps.InfoWindow({
          content: venue.name + "
 Rating: "+venue.rating
        });

        var markerIsActive = false;

        //create event listener to open info window
        google.maps.event.addListener(marker, 'mouseover', function() {
          if(!markerIsActive){
            infowindow.open(map, this);
          }
        }); //mouseover

        // create event listener to close info window
        google.maps.event.addListener(marker, 'mouseout', function() {
          if(!markerIsActive){
            infowindow.close();
          }
        }); //mouseout

        // create event listener to close info window
        google.maps.event.addListener(marker, 'click', function() {
          if(markerIsActive){ // deactivate this marker
            markerIsActive = false;
            infowindow.close();

          }else if(!markerIsActive){ //activate this marker
            markerIsActive = true;
            if(window.activeInfoWindow){
              window.activeInfoWindow.close(); //close previous
            }
            window.activeInfoWindow = infowindow; //update current;
          } //if
        }); //mouseout

        google.maps.event.addListener(marker, 'dblclick', function() {
          component.openFourSquare(venue); //load new page

        });

        //show map marker
        marker.setMap(map);
        // add current marker to state
        component.state.displayedMarkers[venue.id] = marker;
        // component.state.displayedMarkers.push(marker);
      } //if(marker)

      //display markers
    }); //forEach
  }, //updateMapMarkers()

  // clear map markers
  clearMapMarkers (){
    var markers = this.state.markers;

    for(var key in markers){
      var marker = markers[key];
      marker.setMap(null);
    } //for

    this.state.markers = {};
  }, //clearMapMarkers

  render () {
    // var component = this;

    // var listDetails = VenueStore.getVenues().map(function(venue, index) {
    //   return (
    //     <VenueView venue={venue}/>
    //   )
    // });

    return (

    );
  }
});

module.exports = MapView;<|endoftext|>


<commit_before>'use strict';

var sendChannel;
var sendButton = document.getElementById("sendButton");
var sendTextarea = document.getElementById("dataChannelSend");
var receiveTextarea = document.getElementById("dataChannelReceive");

sendButton.onclick = sendData;

var isChannelReady;
var isInitiator;
var isStarted;
var localStream;
var pc;
var remoteStream;
var turnReady;

var pc_config = webrtcDetectedBrowser === 'firefox' ?
  {'iceServers':[{'url':'stun:23.21.150.121'}]} : // number IP
  {'iceServers': [{'url': 'stun:stun.l.google.com:19302'}]};

var pc_constraints = {
  'optional': [
    {'DtlsSrtpKeyAgreement': true},
    {'RtpDataChannels': true}
  ]};

// Set up audio and video regardless of what devices are present.
var sdpConstraints = {'mandatory': {
  'OfferToReceiveAudio':true,
  'OfferToReceiveVideo':true }};

/////////////////////////////////////////////

var room = location.pathname.substring(1);
if (room === '') {
//  room = prompt('Enter room name:');
  room = 'foo';
} else {
  //
}

var socket = io.connect();

if (room !== '') {
  console.log('Create or join room', room);
  socket.emit('create or join', room);
}

socket.on('created', function (room){
  console.log('Created room ' + room);
  isInitiator = true;
});

socket.on('full', function (room){
  console.log('Room ' + room + ' is full');
});

socket.on('join', function (room){
  console.log('Another peer made a request to join room ' + room);
  console.log('This peer is the initiator of room ' + room + '!');
  isChannelReady = true;
});

socket.on('joined', function (room){
  console.log('This peer has joined room ' + room);
  isChannelReady = true;
});

socket.on('log', function (array){
  console.log.apply(console, array);
});

////////////////////////////////////////////////

function sendMessage(message){
	console.log('Sending message: ', message);
  socket.emit('message', message);
}

socket.on('message', function (message){
  console.log('Received message:', message);
  if (message === 'got user media') {
  	maybeStart();
  } else if (message.type === 'offer') {
    if (!isInitiator && !isStarted) {
      maybeStart();
    }
    pc.setRemoteDescription(new RTCSessionDescription(message));
    doAnswer();
  } else if (message.type === 'answer' && isStarted) {
    pc.setRemoteDescription(new RTCSessionDescription(message));
  } else if (message.type === 'candidate' && isStarted) {
    var candidate = new RTCIceCandidate({sdpMLineIndex:message.label,
      candidate:message.candidate});
    pc.addIceCandidate(candidate);
  } else if (message === 'bye' && isStarted) {
    handleRemoteHangup();
  }
});

////////////////////////////////////////////////////

var localVideo = document.querySelector('#localVideo');
var remoteVideo = document.querySelector('#remoteVideo');

function handleUserMedia(stream) {
  localStream = stream;
  attachMediaStream(localVideo, stream);
  console.log('Adding local stream.');
  sendMessage('got user media');
  if (isInitiator) {
    maybeStart();
  }
}

function handleUserMediaError(error){
  console.log('getUserMedia error: ', error);
}

var constraints = {video: true};

getUserMedia(constraints, handleUserMedia, handleUserMediaError);
console.log('Getting user media with constraints', constraints);

if (location.hostname != "localhost") {
  requestTurn('https://computeengineondemand.appspot.com/turn?username=41784574&key=4080218913');
}

function maybeStart() {
  if (!isStarted && localStream && isChannelReady) {
    createPeerConnection();
    pc.addStream(localStream);
    isStarted = true;
    if (isInitiator) {
      doCall();
    }
  }
}

window.onbeforeunload = function(e){
	sendMessage('bye');
}

/////////////////////////////////////////////////////////

function createPeerConnection() {
  try {
    pc = new RTCPeerConnection(pc_config, pc_constraints);
    pc.onicecandidate = handleIceCandidate;
    console.log('Created RTCPeerConnnection with:\n' +
      '  config: \'' + JSON.stringify(pc_config) + '\';\n' +
      '  constraints: \'' + JSON.stringify(pc_constraints) + '\'.');
  } catch (e) {
    console.log('Failed to create PeerConnection, exception: ' + e.message);
    alert('Cannot create RTCPeerConnection object.');
      return;
  }
  pc.onaddstream = handleRemoteStreamAdded;
  pc.onremovestream = handleRemoteStreamRemoved;

  if (isInitiator) {
    try {
      // Reliable Data Channels not yet supported in Chrome
      sendChannel = pc.createDataChannel("sendDataChannel",
        {reliable: false});
      sendChannel.onmessage = handleMessage;
      trace('Created send data channel');
    } catch (e) {
      alert('Failed to create data channel. ' +
            'You need Chrome M25 or later with RtpDataChannel enabled');
      trace('createDataChannel() failed with exception: ' + e.message);
    }
    sendChannel.onopen = handleSendChannelStateChange;
    sendChannel.onclose = handleSendChannelStateChange;
  } else {
    pc.ondatachannel = gotReceiveChannel;
  }
}

function sendData() {
  var data = sendTextarea.value;
  sendChannel.send(data);
  trace('Sent data: ' + data);
}

// function closeDataChannels() {
//   trace('Closing data channels');
//   sendChannel.close();
//   trace('Closed data channel with label: ' + sendChannel.label);
//   receiveChannel.close();
//   trace('Closed data channel with label: ' + receiveChannel.label);
//   localPeerConnection.close();
//   remotePeerConnection.close();
//   localPeerConnection = null;
//   remotePeerConnection = null;
//   trace('Closed peer connections');
//   startButton.disabled = false;
//   sendButton.disabled = true;
//   closeButton.disabled = true;
//   dataChannelSend.value = "";
//   dataChannelReceive.value = "";
//   dataChannelSend.disabled = true;
//   dataChannelSend.placeholder = "Press Start, enter some text, then press Send.";
// }

function gotReceiveChannel(event) {
  trace('Receive Channel Callback');
  sendChannel = event.channel;
  sendChannel.onmessage = handleMessage;
  sendChannel.onopen = handleReceiveChannelStateChange;
  sendChannel.onclose = handleReceiveChannelStateChange;
}

function handleMessage(event) {
  trace('Received message: ' + event.data);
  receiveTextarea.value = event.data;
}

function handleSendChannelStateChange() {
  var readyState = sendChannel.readyState;
  trace('Send channel state is: ' + readyState);
  enableMessageInterface(readyState == "open");
}

function handleReceiveChannelStateChange() {
  var readyState = sendChannel.readyState;
  trace('Receive channel state is: ' + readyState);
  enableMessageInterface(readyState == "open");
}

function enableMessageInterface(shouldEnable) {
    if (shouldEnable) {
    dataChannelSend.disabled = false;
    dataChannelSend.focus();
    dataChannelSend.placeholder = "";
    sendButton.disabled = false;
  } else {
    dataChannelSend.disabled = true;
    sendButton.disabled = true;
  }
}

function handleIceCandidate(event) {
  console.log('handleIceCandidate event: ', event);
  if (event.candidate) {
    sendMessage({
      type: 'candidate',
      label: event.candidate.sdpMLineIndex,
      id: event.candidate.sdpMid,
      candidate: event.candidate.candidate});
  } else {
    console.log('End of candidates.');
  }
}

function doCall() {
  var constraints = {'optional': [], 'mandatory': {'MozDontOfferDataChannel': true}};
  // temporary measure to remove Moz* constraints in Chrome
  if (webrtcDetectedBrowser === 'chrome') {
    for (var prop in constraints.mandatory) {
      if (prop.indexOf('Moz') !== -1) {
        delete constraints.mandatory[prop];
      }
     }
   }
  constraints = mergeConstraints(constraints, sdpConstraints);
  console.log('Sending offer to peer, with constraints: \n' +
    '  \'' + JSON.stringify(constraints) + '\'.');
  pc.createOffer(setLocalAndSendMessage, null, constraints);
}

function doAnswer() {
  console.log('Sending answer to peer.');
  pc.createAnswer(setLocalAndSendMessage, null, sdpConstraints);
}

function mergeConstraints(cons1, cons2) {
  var merged = cons1;
  for (var name in cons2.mandatory) {
    merged.mandatory[name] = cons2.mandatory[name];
  }
  merged.optional.concat(cons2.optional);
  return merged;
}

function setLocalAndSendMessage(sessionDescription) {
  // Set Opus as the preferred codec in SDP if Opus is present.
  sessionDescription.sdp = preferOpus(sessionDescription.sdp);
  pc.setLocalDescription(sessionDescription);
  sendMessage(sessionDescription);
}

function requestTurn(turn_url) {
  var turnExists = false;
  for (var i in pc_config.iceServers) {
    if (pc_config.iceServers[i].url.substr(0, 5) === 'turn:') {
      turnExists = true;
      turnReady = true;
      break;
    }
  }
  if (!turnExists) {
    console.log('Getting TURN server from ', turn_url);
    // No TURN server. Get one from computeengineondemand.appspot.com:
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
      if (xhr.readyState === 4 && xhr.status === 200) {
        var turnServer = JSON.parse(xhr.responseText);
      	console.log('Got TURN server: ', turnServer);
        pc_config.iceServers.push({
          'url': 'turn:' + turnServer.username + '@' + turnServer.turn,
          'credential': turnServer.password
        });
        turnReady = true;
      }
    };
    xhr.open('GET', turn_url, true);
    xhr.send();
  }
}

function handleRemoteStreamAdded(event) {
  console.log('Remote stream added.');
 // reattachMediaStream(miniVideo, localVideo);
  attachMediaStream(remoteVideo, event.stream);
  remoteStream = event.stream;
//  waitForRemoteVideo();
}
function handleRemoteStreamRemoved(event) {
  console.log('Remote stream removed. Event: ', event);
}

function hangup() {
  console.log('Hanging up.');
  stop();
  sendMessage('bye');
}

function handleRemoteHangup() {
  console.log('Session terminated.');
  stop();
  isInitiator = false;
}

function stop() {
  isStarted = false;
  // isAudioMuted = false;
  // isVideoMuted = false;
  pc.close();
  pc = null;
}

///////////////////////////////////////////

// Set Opus as the default audio codec if it's present.
function preferOpus(sdp) {
  var sdpLines = sdp.split('\r\n');
  var mLineIndex;
  // Search for m line.
  for (var i = 0; i < sdpLines.length; i++) {
      if (sdpLines[i].search('m=audio') !== -1) {
        mLineIndex = i;
        break;
      }
  }
  if (mLineIndex === null) {
    return sdp;
  }

  // If Opus is available, set it as the default in m line.
  for (i = 0; i < sdpLines.length; i++) {
    if (sdpLines[i].search('opus/48000') !== -1) {
      var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i);
      if (opusPayload) {
        sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], opusPayload);
      }
      break;
    }
  }

  // Remove CN in m line and sdp.
  sdpLines = removeCN(sdpLines, mLineIndex);

  sdp = sdpLines.join('\r\n');
  return sdp;
}

function extractSdp(sdpLine, pattern) {
  var result = sdpLine.match(pattern);
  return result && result.length === 2 ? result[1] : null;
}

// Set the selected codec to the first in m line.
function setDefaultCodec(mLine, payload) {
  var elements = mLine.split(' ');
  var newLine = [];
  var index = 0;
  for (var i = 0; i < elements.length; i++) {
    if (index === 3) { // Format of media starts from the fourth.
      newLine[index++] = payload; // Put target payload to the first.
    }
    if (elements[i] !== payload) {
      newLine[index++] = elements[i];
    }
  }
  return newLine.join(' ');
}

// Strip CN from sdp before CN constraints is ready.
function removeCN(sdpLines, mLineIndex) {
  var mLineElements = sdpLines[mLineIndex].split(' ');
  // Scan from end for the convenience of removing an item.
  for (var i = sdpLines.length-1; i >= 0; i--) {
    var payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i);
    if (payload) {
      var cnPos = mLineElements.indexOf(payload);
      if (cnPos !== -1) {
        // Remove CN payload from m line.
        mLineElements.splice(cnPos, 1);
      }
      // Remove CN line in sdp
      sdpLines.splice(i, 1);
    }
  }

  sdpLines[mLineIndex] = mLineElements.join(' ');
  return sdpLines;
}

<commit_msg>baseline for sending data between browsers.<commit_after>'use strict';

var sendChannel;
var sendButton = document.getElementById("sendButton");
var sendTextarea = document.getElementById("dataChannelSend");
var receiveTextarea = document.getElementById("dataChannelReceive");

sendButton.onclick = sendData;

var isChannelReady;
var isInitiator;
var isStarted;
var localStream;
var pc;
var remoteStream;
var turnReady;

var pc_config = webrtcDetectedBrowser === 'firefox' ?
  {'iceServers':[{'url':'stun:23.21.150.121'}]} : // number IP
  {'iceServers': [{'url': 'stun:stun.l.google.com:19302'}]};

var pc_constraints = {
  'optional': [
    {'DtlsSrtpKeyAgreement': true},
    {'RtpDataChannels': true}
  ]};

// Set up audio and video regardless of what devices are present.
var sdpConstraints = {'mandatory': {
  'OfferToReceiveAudio':true,
  'OfferToReceiveVideo':true }};

/////////////////////////////////////////////

var room = location.pathname.substring(1);
if (room === '') {
//  room = prompt('Enter room name:');
  room = 'foo';
} else {
  //
}

var socket = io.connect();

if (room !== '') {
  console.log('Create or join room', room);
  socket.emit('create or join', room);
}

socket.on('created', function (room){
  console.log('Created room ' + room);
  isInitiator = true;
});

socket.on('full', function (room){
  console.log('Room ' + room + ' is full');
});

socket.on('join', function (room){
  console.log('Another peer made a request to join room ' + room);
  console.log('This peer is the initiator of room ' + room + '!');
  isChannelReady = true;
});

socket.on('joined', function (room){
  console.log('This peer has joined room ' + room);
  isChannelReady = true;
});

socket.on('log', function (array){
  console.log.apply(console, array);
});

////////////////////////////////////////////////

function sendMessage(message){
	console.log('Sending message: ', message);
  socket.emit('message', message);
}

socket.on('message', function (message){
  console.log('Received message:', message);
  if (message === 'got user media') {
  	maybeStart();
  } else if (message.type === 'offer') {
    if (!isInitiator && !isStarted) {
      maybeStart();
    }
    pc.setRemoteDescription(new RTCSessionDescription(message));
    doAnswer();
  } else if (message.type === 'answer' && isStarted) {
    pc.setRemoteDescription(new RTCSessionDescription(message));
  } else if (message.type === 'candidate' && isStarted) {
    var candidate = new RTCIceCandidate({sdpMLineIndex:message.label,
      candidate:message.candidate});
    pc.addIceCandidate(candidate);
  } else if (message === 'bye' && isStarted) {
    handleRemoteHangup();
  }
});

////////////////////////////////////////////////////

function handleUserMedia(stream) {
  localStream = stream;
  attachMediaStream(localVideo, stream);
  console.log('Adding local stream.');
  sendMessage('got user media');
  if (isInitiator) {
    maybeStart();
  }
}

function handleUserMediaError(error){
  console.log('getUserMedia error: ', error);
}

var constraints = null;//{video: true};

  sendMessage('got user media');

//getUserMedia(constraints, handleUserMedia, handleUserMediaError);
//console.log('Getting user media with constraints', constraints);

if (location.hostname != "localhost") {
  requestTurn('https://computeengineondemand.appspot.com/turn?username=41784574&key=4080218913');
}

function maybeStart() {
  if (!isStarted && isChannelReady) {
    createPeerConnection();
    //pc.addStream(localStream);
    isStarted = true;
    if (isInitiator) {
      doCall();
    }
  }
}

window.onbeforeunload = function(e){
	sendMessage('bye');
}

/////////////////////////////////////////////////////////

function createPeerConnection() {
  try {
    pc = new RTCPeerConnection(null);
    pc.onicecandidate = handleIceCandidate;
    console.log('Created RTCPeerConnnection with:\n' +
      '  config: \'' + JSON.stringify(pc_config) + '\';\n' +
      '  constraints: \'' + JSON.stringify(pc_constraints) + '\'.');
  } catch (e) {
    console.log('Failed to create PeerConnection, exception: ' + e.message);
    alert('Cannot create RTCPeerConnection object.');
      return;
  }
  pc.onaddstream = handleRemoteStreamAdded;
  pc.onremovestream = handleRemoteStreamRemoved;

  if (isInitiator) {
    try {
      // Reliable Data Channels not yet supported in Chrome
      sendChannel = pc.createDataChannel("sendDataChannel",
        {reliable: false});
      sendChannel.onmessage = handleMessage;
      trace('Created send data channel');
    } catch (e) {
      alert('Failed to create data channel. ' +
            'You need Chrome M25 or later with RtpDataChannel enabled');
      trace('createDataChannel() failed with exception: ' + e.message);
    }
    sendChannel.onopen = handleSendChannelStateChange;
    sendChannel.onclose = handleSendChannelStateChange;
  } else {
    pc.ondatachannel = gotReceiveChannel;
  }
}

function sendData() {
  var data = sendTextarea.value;
  sendChannel.send(data);
  trace('Sent data: ' + data);
}

// function closeDataChannels() {
//   trace('Closing data channels');
//   sendChannel.close();
//   trace('Closed data channel with label: ' + sendChannel.label);
//   receiveChannel.close();
//   trace('Closed data channel with label: ' + receiveChannel.label);
//   localPeerConnection.close();
//   remotePeerConnection.close();
//   localPeerConnection = null;
//   remotePeerConnection = null;
//   trace('Closed peer connections');
//   startButton.disabled = false;
//   sendButton.disabled = true;
//   closeButton.disabled = true;
//   dataChannelSend.value = "";
//   dataChannelReceive.value = "";
//   dataChannelSend.disabled = true;
//   dataChannelSend.placeholder = "Press Start, enter some text, then press Send.";
// }

function gotReceiveChannel(event) {
  trace('Receive Channel Callback');
  sendChannel = event.channel;
  sendChannel.onmessage = handleMessage;
  sendChannel.onopen = handleReceiveChannelStateChange;
  sendChannel.onclose = handleReceiveChannelStateChange;
}

function handleMessage(event) {
  trace('Received message: ' + event.data);
  receiveTextarea.value = event.data;
}

function handleSendChannelStateChange() {
  var readyState = sendChannel.readyState;
  trace('Send channel state is: ' + readyState);
  enableMessageInterface(readyState == "open");
}

function handleReceiveChannelStateChange() {
  var readyState = sendChannel.readyState;
  trace('Receive channel state is: ' + readyState);
  enableMessageInterface(readyState == "open");
}

function enableMessageInterface(shouldEnable) {
    if (shouldEnable) {
    dataChannelSend.disabled = false;
    dataChannelSend.focus();
    dataChannelSend.placeholder = "";
    sendButton.disabled = false;
  } else {
    dataChannelSend.disabled = true;
    sendButton.disabled = true;
  }
}

function handleIceCandidate(event) {
  console.log('handleIceCandidate event: ', event);
  if (event.candidate) {
    sendMessage({
      type: 'candidate',
      label: event.candidate.sdpMLineIndex,
      id: event.candidate.sdpMid,
      candidate: event.candidate.candidate});
  } else {
    console.log('End of candidates.');
  }
}

function doCall() {
  // var constraints = {'optional': [], 'mandatory': {'MozDontOfferDataChannel': true}};
  // // temporary measure to remove Moz* constraints in Chrome
  // if (webrtcDetectedBrowser === 'chrome') {
  //   for (var prop in constraints.mandatory) {
  //     if (prop.indexOf('Moz') !== -1) {
  //       delete constraints.mandatory[prop];
  //     }
  //    }
  //  }
  // constraints = mergeConstraints(constraints, sdpConstraints);
  // console.log('Sending offer to peer, with constraints: \n' +
  //   '  \'' + JSON.stringify(constraints) + '\'.');
  pc.createOffer(setLocalAndSendMessage, null);//, constraints);
}

function doAnswer() {
  console.log('Sending answer to peer.');
  pc.createAnswer(setLocalAndSendMessage, null, sdpConstraints);
}

function mergeConstraints(cons1, cons2) {
  var merged = cons1;
  for (var name in cons2.mandatory) {
    merged.mandatory[name] = cons2.mandatory[name];
  }
  merged.optional.concat(cons2.optional);
  return merged;
}

function setLocalAndSendMessage(sessionDescription) {
  // Set Opus as the preferred codec in SDP if Opus is present.
  //sessionDescription.sdp = preferOpus(sessionDescription.sdp);
  pc.setLocalDescription(sessionDescription);
  sendMessage(sessionDescription);
}

function requestTurn(turn_url) {
  var turnExists = false;
  for (var i in pc_config.iceServers) {
    if (pc_config.iceServers[i].url.substr(0, 5) === 'turn:') {
      turnExists = true;
      turnReady = true;
      break;
    }
  }
  if (!turnExists) {
    console.log('Getting TURN server from ', turn_url);
    // No TURN server. Get one from computeengineondemand.appspot.com:
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
      if (xhr.readyState === 4 && xhr.status === 200) {
        var turnServer = JSON.parse(xhr.responseText);
      	console.log('Got TURN server: ', turnServer);
        pc_config.iceServers.push({
          'url': 'turn:' + turnServer.username + '@' + turnServer.turn,
          'credential': turnServer.password
        });
        turnReady = true;
      }
    };
    xhr.open('GET', turn_url, true);
    xhr.send();
  }
}

function handleRemoteStreamAdded(event) {
  console.log('Remote stream added.');
 // reattachMediaStream(miniVideo, localVideo);
  attachMediaStream(remoteVideo, event.stream);
  remoteStream = event.stream;
//  waitForRemoteVideo();
}
function handleRemoteStreamRemoved(event) {
  console.log('Remote stream removed. Event: ', event);
}

function hangup() {
  console.log('Hanging up.');
  stop();
  sendMessage('bye');
}

function handleRemoteHangup() {
  console.log('Session terminated.');
  stop();
  isInitiator = false;
}

function stop() {
  isStarted = false;
  // isAudioMuted = false;
  // isVideoMuted = false;
  pc.close();
  pc = null;
}

///////////////////////////////////////////

// Set Opus as the default audio codec if it's present.
function preferOpus(sdp) {
  var sdpLines = sdp.split('\r\n');
  var mLineIndex;
  // Search for m line.
  for (var i = 0; i < sdpLines.length; i++) {
      if (sdpLines[i].search('m=audio') !== -1) {
        mLineIndex = i;
        break;
      }
  }
  if (mLineIndex === null) {
    return sdp;
  }

  // If Opus is available, set it as the default in m line.
  for (i = 0; i < sdpLines.length; i++) {
    if (sdpLines[i].search('opus/48000') !== -1) {
      var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i);
      if (opusPayload) {
        sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], opusPayload);
      }
      break;
    }
  }

  // Remove CN in m line and sdp.
  sdpLines = removeCN(sdpLines, mLineIndex);

  sdp = sdpLines.join('\r\n');
  return sdp;
}

function extractSdp(sdpLine, pattern) {
  var result = sdpLine.match(pattern);
  return result && result.length === 2 ? result[1] : null;
}

// Set the selected codec to the first in m line.
function setDefaultCodec(mLine, payload) {
  var elements = mLine.split(' ');
  var newLine = [];
  var index = 0;
  for (var i = 0; i < elements.length; i++) {
    if (index === 3) { // Format of media starts from the fourth.
      newLine[index++] = payload; // Put target payload to the first.
    }
    if (elements[i] !== payload) {
      newLine[index++] = elements[i];
    }
  }
  return newLine.join(' ');
}

// Strip CN from sdp before CN constraints is ready.
function removeCN(sdpLines, mLineIndex) {
  var mLineElements = sdpLines[mLineIndex].split(' ');
  // Scan from end for the convenience of removing an item.
  for (var i = sdpLines.length-1; i >= 0; i--) {
    var payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i);
    if (payload) {
      var cnPos = mLineElements.indexOf(payload);
      if (cnPos !== -1) {
        // Remove CN payload from m line.
        mLineElements.splice(cnPos, 1);
      }
      // Remove CN line in sdp
      sdpLines.splice(i, 1);
    }
  }

  sdpLines[mLineIndex] = mLineElements.join(' ');
  return sdpLines;
}

<|endoftext|>


<commit_before>import {createStore, applyMiddleware, combineReducers, compose} from 'redux';

const rootReducer = combineReducers({});
const env = process.env.NODE_ENV;
export default function configureStore(initialState = {}) {
  let enhancer = applyMiddleware({});
  if (env === 'development') {
    const devTools = window.devToolsExtension ? window.devToolsExtension() : f => f;
    enhancer = compose(applyMiddleware({}), devTools);
  }
  return createStore(
    rootReducer,
    initialState,
    enhancer
  );
}
<commit_msg>Fixed rootReducer issue.<commit_after>import {createStore, applyMiddleware, combineReducers, compose} from 'redux';

const rootReducer = combineReducers({root: () => ''});
const env = process.env.NODE_ENV;
export default function configureStore(initialState = {}) {
  let enhancer = applyMiddleware({});
  if (env === 'development') {
    const devTools = window.devToolsExtension ? window.devToolsExtension() : f => f;
    enhancer = compose(applyMiddleware({}), devTools);
  }
  return createStore(
    rootReducer,
    initialState,
    enhancer
  );
}
<|endoftext|>


<commit_before>// Require modules
const https = require('https');
const github_graphql = require('github-graphql-client');
const semver = require('semver');
const query = require('./query');
const schemeMapper = require('./scheme-mapper');
const pkg = require('../package.json');

/**
 * Executes a GraphQL query on the API to fetch either the latest release or tag.
 * The returned version is compared to the given version.
 * When the fetched version is greater than the given one, the newer version
 * is returned.
 *
 * @param options {object} The options for the version check.
 * @param callback {function|undefined} The callback function.
 */
const graphql = (options, callback) => {
	// build the query
	const theQuery = options.fetchTags ? query.tags(options.repo, options.owner) : query.releases(options.repo, options.owner);

	// do the api call
	github_graphql({
		token: options.token,
		query: theQuery
	}, (err, res) => {
		if (err) {
			callback(err, null);
		} else {
			// Retrieve newer version name
			const newer = options.fetchTags ? res.data.repository.refs.nodes[0] : res.data.repository.releases.nodes[0];

			// Compare versions
			if (semver.gt((options.fetchTags ? newer.name : newer.tag.name), options.currentVersion)) {
				callback(null, newer);
			} else {
				callback(null, null);
			}
		}
	});
};

/**
 * Executes an API call on the Github Rest API (v3) that should return the latest version.
 * The returned version is compared to the given version.
 * When the fetched version is greater than the given one, the newer version
 * is returned.
 *
 * @param options {object} The options for the version check.
 * @param callback {function|undefined} The callback function.
*/
const rest = (options, callback) => {
	const handler = res => {
		const chunks = [];
		res.on('data', chunk => {
			return chunks.push(chunk.toString());
		});
		res.on('end', () => {
			// parse response string into an object
			const response = chunks.join('');
			let json = null;
			try {
				json = JSON.parse(response);
			} catch (error) {
				return callback(error, null);
			}

			// 404 error occurs, when no releases are found
			if (res.statusCode === 404) {
				return callback(null, null);
			}

			// status codes other than 200 are treated as an error
			else if (res.statusCode !== 200) {
				return callback(new Error(json.message), null);
			}

			// Compare versions
			let found = false;
			let version = null;
			for (let i = 0; i < json.length; i++) {
				version = json[i];

				if (options.filterPrerelease) {
					if(version['prerelease'] !== undefined && version['prerelease']) {
					  continue;
					}
				}

				if (semver.gt(version[options.fetchTags ? 'name' : 'tag_name'], options.currentVersion)) {
					found = true;
					break;
				}
			}

			if (found) {
				const mapped = schemeMapper[options.fetchTags ? 'tag' : 'release'](version);
				callback(null, mapped);
			} else {
				callback(null, null);
			}
		});
	};

	// build url
	let apiUrl = `/repos/${options.owner}/${options.repo}`;
	if (options.fetchTags) {
		apiUrl += '/tags';
	} else {
		apiUrl += '/releases';

		if (options.latestOnly) {
			apiUrl += '/latest';
		}
	}

	// define request options
	const opts = {
		hostname: 'api.github.com',
		path: apiUrl,
		headers: {
			'Accept': 'application/vnd.github.v3+json',
			'User-Agent': `${pkg.name} v${pkg.version}`
		}
	};

	// execute request
	let req = https.get(opts, handler);
	req.on('error', err => {
		callback(err, null);
	});
	req.end();
};

/**
 * Checks whether a new version is available. Depending on whether a token is given, the
 * Github GraphQL API (v4) will be used. Otherwise we rely on the Github Rest API (v3), which
 * does not require authentication.
 *
 * @param options {object} The options for the version check.
 * @param callback {function|undefined} The callback function.
 */
module.exports = (options, callback) => {
	if (options === null || options === undefined) {
		throw new Error('options object must not be null or undefined!');
	}

	// get options
	options.token = options.token || process.env.GITHUB_API_TOKEN || undefined;
	if (options.reduceTraffic) {
		console.warn('The "reduceTraffic" option is deprecated! Consider updating "github-version-checker" to a newer version.');
	}

	// check if required options are defined
	if (!options.repo) {
		callback('no repository specified', null);
		return;
	}
	if (!options.owner) {
		callback('no owner specified', null);
		return;
	}
	if (!options.currentVersion) {
		callback('no current version given', null);
		return;
	}

	// decide what to do
	// when we have a token supplied, we will call the GraphQL api
	if (options.token) {

		if (options.filterPrerelease) {
			throw new Error(`filterPrerelease option currently unsupported when specifying a token.`);
		}

		graphql(options, callback);
	} else {
		rest(options, callback);
	}
};
<commit_msg>fixed linting error<commit_after>// Require modules
const https = require('https');
const github_graphql = require('github-graphql-client');
const semver = require('semver');
const query = require('./query');
const schemeMapper = require('./scheme-mapper');
const pkg = require('../package.json');

/**
 * Executes a GraphQL query on the API to fetch either the latest release or tag.
 * The returned version is compared to the given version.
 * When the fetched version is greater than the given one, the newer version
 * is returned.
 *
 * @param options {object} The options for the version check.
 * @param callback {function|undefined} The callback function.
 */
const graphql = (options, callback) => {
	// build the query
	const theQuery = options.fetchTags ? query.tags(options.repo, options.owner) : query.releases(options.repo, options.owner);

	// do the api call
	github_graphql({
		token: options.token,
		query: theQuery
	}, (err, res) => {
		if (err) {
			callback(err, null);
		} else {
			// Retrieve newer version name
			const newer = options.fetchTags ? res.data.repository.refs.nodes[0] : res.data.repository.releases.nodes[0];

			// Compare versions
			if (semver.gt((options.fetchTags ? newer.name : newer.tag.name), options.currentVersion)) {
				callback(null, newer);
			} else {
				callback(null, null);
			}
		}
	});
};

/**
 * Executes an API call on the Github Rest API (v3) that should return the latest version.
 * The returned version is compared to the given version.
 * When the fetched version is greater than the given one, the newer version
 * is returned.
 *
 * @param options {object} The options for the version check.
 * @param callback {function|undefined} The callback function.
*/
const rest = (options, callback) => {
	const handler = res => {
		const chunks = [];
		res.on('data', chunk => {
			return chunks.push(chunk.toString());
		});
		res.on('end', () => {
			// parse response string into an object
			const response = chunks.join('');
			let json = null;
			try {
				json = JSON.parse(response);
			} catch (error) {
				return callback(error, null);
			}

			// 404 error occurs, when no releases are found
			if (res.statusCode === 404) {
				return callback(null, null);
			}

			// status codes other than 200 are treated as an error
			else if (res.statusCode !== 200) {
				return callback(new Error(json.message), null);
			}

			// Compare versions
			let found = false;
			let version = null;
			for (let i = 0; i < json.length; i++) {
				version = json[i];

				if (options.filterPrerelease) {
					if(version['prerelease'] !== undefined && version['prerelease']) {
						continue;
					}
				}

				if (semver.gt(version[options.fetchTags ? 'name' : 'tag_name'], options.currentVersion)) {
					found = true;
					break;
				}
			}

			if (found) {
				const mapped = schemeMapper[options.fetchTags ? 'tag' : 'release'](version);
				callback(null, mapped);
			} else {
				callback(null, null);
			}
		});
	};

	// build url
	let apiUrl = `/repos/${options.owner}/${options.repo}`;
	if (options.fetchTags) {
		apiUrl += '/tags';
	} else {
		apiUrl += '/releases';

		if (options.latestOnly) {
			apiUrl += '/latest';
		}
	}

	// define request options
	const opts = {
		hostname: 'api.github.com',
		path: apiUrl,
		headers: {
			'Accept': 'application/vnd.github.v3+json',
			'User-Agent': `${pkg.name} v${pkg.version}`
		}
	};

	// execute request
	let req = https.get(opts, handler);
	req.on('error', err => {
		callback(err, null);
	});
	req.end();
};

/**
 * Checks whether a new version is available. Depending on whether a token is given, the
 * Github GraphQL API (v4) will be used. Otherwise we rely on the Github Rest API (v3), which
 * does not require authentication.
 *
 * @param options {object} The options for the version check.
 * @param callback {function|undefined} The callback function.
 */
module.exports = (options, callback) => {
	if (options === null || options === undefined) {
		throw new Error('options object must not be null or undefined!');
	}

	// get options
	options.token = options.token || process.env.GITHUB_API_TOKEN || undefined;
	if (options.reduceTraffic) {
		console.warn('The "reduceTraffic" option is deprecated! Consider updating "github-version-checker" to a newer version.');
	}

	// check if required options are defined
	if (!options.repo) {
		callback('no repository specified', null);
		return;
	}
	if (!options.owner) {
		callback('no owner specified', null);
		return;
	}
	if (!options.currentVersion) {
		callback('no current version given', null);
		return;
	}

	// decide what to do
	// when we have a token supplied, we will call the GraphQL api
	if (options.token) {

		if (options.filterPrerelease) {
			throw new Error('filterPrerelease option currently unsupported when specifying a token.');
		}

		graphql(options, callback);
	} else {
		rest(options, callback);
	}
};
<|endoftext|>


<commit_before>// on startup run resizing event
Meteor.startup(function () {
    $(window).resize(function () {
        $('#map').css('height', window.innerHeight);
    });
    $(window).resize(); // trigger resize event
});

// create marker collection
var Markers = new Meteor.Collection('markers');
Meteor.subscribe("markers");

//create trashesCollection
var trashesCollection = new Meteor.Collection('trashesCollection');

//if template "map" is renderd
Template.map.rendered = function () {
    //subscribe to trashesCollection
    Meteor.subscribe('trashesCollection', function () {
        var trashesData = trashesCollection.find().fetch();
        //callback to setTrashes
        setTrashes(trashesData)
    });

    HTTP.get(Meteor.absoluteUrl("/map.json"), function (err, result) {
        var geoData = result.data;
        geoDatafunction(geoData)
    });

    //create leaflet map and start coordiates
    var map = L.map('map', {
        center: [52.376956, 4.902756],
        maxZoom: 14,
        minZoom: 14,
        zoom: 14
    });

    //add bounds to map
    map.fitBounds([
    [52.380419542018174, 4.941530227661133],
     [52.359457601988254, 4.864282608032227]
   ]);

    //create div icon with class trash
    var trashIcon = L.divIcon({
        className: 'trash'
    });

    //disable dragging
    map.dragging.disable();
    map.touchZoom.disable();
    map.doubleClickZoom.disable();
    map.scrollWheelZoom.disable();
    map.boxZoom.disable();
    map.keyboard.disable();

    //set trashes on map
    var setTrashes = function (trashesData) {
        var amountTrashes = trashesData.length,
            i = 0;
        for (i; i < amountTrashes; i++) {
            var longitude = trashesData[i].log;
            var latitude = trashesData[i].lat;
            var street = trashesData[i].street;
            var number = trashesData[i].houseNumber;
            L.marker([latitude, longitude], {
                icon: trashIcon,
                riseOnHover: true,
            }).addTo(map).bindPopup(street + number);
        }
    };

//Create the map of Amsterdam Centrum and add render it.
    var myStyle = {
        "fillColor": "#F0F0F0",
        "fillOpacity": 1,
        "color": "#FFFFFF"
    }

    var geojson;

//What happens on mouseover
    function highlightFeature(e) {
        var layer = e.target;

        layer.setStyle({
            weight: 5,
            fillColor: '#D83E41',
            dashArray: '',
            fillOpacity: 0.7
        });

        if (!L.Browser.ie && !L.Browser.opera) {
            layer.bringToFront();
        }
    }

    //reset on mouseout
    function resetHighlight(e) {
        geojson.resetStyle(e.target);
    }

    function onEachFeature(feature, layer) {
        layer.on({
            mouseover: highlightFeature,
            mouseout: resetHighlight
        });
    }

    var geoDatafunction = function (geoData) {
        geojson = L.geoJson(geoData, {
            style: myStyle,
            onEachFeature: onEachFeature
        }).addTo(map);
    }
<<<<<<< Updated upstream
};
=======

};
>>>>>>> Stashed changes
<commit_msg>hide zoomControl<commit_after>// on startup run resizing event
Meteor.startup(function () {
    $(window).resize(function () {
        $('#map').css('height', window.innerHeight);
    });
    $(window).resize(); // trigger resize event
});

// create marker collection
var Markers = new Meteor.Collection('markers');
Meteor.subscribe("markers");

//create trashesCollection
var trashesCollection = new Meteor.Collection('trashesCollection');

//if template "map" is renderd
Template.map.rendered = function () {
    //subscribe to trashesCollection
    Meteor.subscribe('trashesCollection', function () {
        var trashesData = trashesCollection.find().fetch();
        //callback to setTrashes
        setTrashes(trashesData)
    });

    HTTP.get(Meteor.absoluteUrl("/map.json"), function (err, result) {
        var geoData = result.data;
        geoDatafunction(geoData)
    });

    //create leaflet map and start coordiates
    var map = L.map('map', {
        center: [52.376956, 4.902756],
        maxZoom: 14,
        minZoom: 14,
        zoom: 14,
        zoomControl:false
    });

    //add bounds to map
    map.fitBounds([
    [52.380419542018174, 4.941530227661133],
     [52.359457601988254, 4.864282608032227]
   ]);

    //create div icon with class trash
    var trashIcon = L.divIcon({
        className: 'trash'
    });

    //disable dragging
    map.dragging.disable();
    map.touchZoom.disable();
    map.doubleClickZoom.disable();
    map.scrollWheelZoom.disable();
    map.boxZoom.disable();
    map.keyboard.disable();

    //set trashes on map
    var setTrashes = function (trashesData) {
        var amountTrashes = trashesData.length,
            i = 0;
        for (i; i < amountTrashes; i++) {
            var longitude = trashesData[i].log;
            var latitude = trashesData[i].lat;
            var street = trashesData[i].street;
            var number = trashesData[i].houseNumber;
            L.marker([latitude, longitude], {
                icon: trashIcon,
                riseOnHover: true,
            }).addTo(map).bindPopup(street + number);
        }
    };

    //Create the map of Amsterdam Centrum and add render it.
    var myStyle = {
        "fillColor": "#F0F0F0",
        "fillOpacity": 1,
        "color": "#FFFFFF"
    }
    var geojson;

    //What happens on mouseover
    function highlightFeature(e) {
        var layer = e.target;

        layer.setStyle({
            weight: 5,
            fillColor: '#D83E41',
            dashArray: '',
            fillOpacity: 0.7
        });

        if (!L.Browser.ie && !L.Browser.opera) {
            layer.bringToFront();
        }
    }

    //reset on mouseout
    function resetHighlight(e) {
        geojson.resetStyle(e.target);
    }

    function onEachFeature(feature, layer) {
        layer.on({
            mouseover: highlightFeature,
            mouseout: resetHighlight
        });
    }

    var geoDatafunction = function (geoData) {
        geojson = L.geoJson(geoData, {
            style: myStyle,
            onEachFeature: onEachFeature
        }).addTo(map);
    }
};
<|endoftext|>


<commit_before>var _     = require('lodash');
var soap  = require('soap');
var async = require('async');

function Clang(config) {

  if (!(this instanceof Clang)) {
    return new Clang(config);
  }
  this.config = _.clone(config || {});
  this.api    = null;
}

Clang.prototype.init = function(callback) {
  var me = this;
  if (me.config.debug) {
    console.log('Creating SOAP client');
  }

  soap.createClient('https://secure.myclang.com/app/api/soap/public/index.php?wsdl', function(err, result) {
    if (err) {
      return callback(err);
    }

    if (me.config.debug) {
      console.log('SOAP client created');
    }
    me.api = result;

    callback(null);
  });
};

Clang.prototype.request = function(methodName, args, callback) {
  var me = this;
  var localArgs;

  if (arguments.length === 2) {
    callback = args;
    localArgs = {
      uuid: me.config.uuid
    };
  } else if (arguments.length === 3) {
    localArgs = _.assign({
      uuid: me.config.uuid
    }, args || {});
  } else {
    throw new Error('request takes 3 arguments: methodName, args (object) and callback function');
  }

  if (!localArgs.uuid) {
    return setImmediate(function() {
      callback(new Error('uuid missing. Provide it with the 2nd arguments object or with client instantiation. Hint: `var clang = new Clang({uuid: \'12345678-...\'})`'));
    });
  }

  async.waterfall([
    function async_init(callback){
      if (me.api) {
        return setImmediate(callback);
      }
      me.init(callback);
    },
    function async_request(callback){
      var fn = me.api[methodName];

      if (!fn) {
        return setImmediate(function() {
          callback(new Error('Undefined method `' + methodName + '`'));
        });
      }

      fn(localArgs, buildCallback(me.config, me.api, callback));
    }
  ], callback);
};

var setMethods = {
  CUSTOMER_SET: 'customerSet_getCustomers',
  MAILING_SET : 'mailingSet_getMailings',
  OPEN_SET    : 'openSet_getOpens',
  CLICK_SET   : 'clickSet_getClicks',
  BOUNCE_SET  : 'bounceSet_getBounces'
};

var normalizeResponse = function(config, result) {
  if (result.msg === true) {
    if (config.debug) {
      console.log('SOAP success');
    }
    return [{msg: true}];
  }

  var msgKeys = Object.keys(result.msg);
  if (msgKeys.length === 0) {
    if (config.debug) {
      console.log('No records found in SOAP response');
    }
    return [];
  }
  if (msgKeys.length === 1 && result.msg[msgKeys[0]] instanceof Array) {
    if (config.debug) {
      console.log('SOAP msg array returned'); //{ code: 0, msg: { Group: [Object] } }
    }
    return result.msg[msgKeys[0]];
  }
  if (result.msg) { // 1 record from x_getById or x_create
    if (config.debug) {
      console.log('SOAP msg object returned');
    }
    return [result.msg];
  }
};

/**
 * Use this callback builder for clang method that use a resource for the dataset. It deals with:
 * - getting a resource id status
 * - getting the data set when the resource is READY
 * - normalizing the response
 * @param api - is reference to a previously created soap client with Clang's wsdl and node-soap
 * @param callback - the method for handling the final data set
 */
var buildCallback = function (config, api, callback) {
  var me = this;

  return function apiCallback(err, result) {
    /*
      first result that indicate there's a recource looks like this:  { code: 0, msg: '210577' }
      second result of fetching resource status looks like this result looks like: {
        code: 0,
        msg: {
          id    : "147082",
          type  : "CUSTOMER_SET",
          status: "READY",
          size  : "1"
        }
      }
    */
    var resourceId;
    if (err) {
      console.log('SOAP error arrived', err.body);
    }

    //Check for actual SOAP Fault generated by callback in soap/lib/client line 152
    if (err) {
      if (err.message.match(/<faultcode>107<\/faultcode>/) &&
          err.message.match(/customer already member of/) )
        return callback(null, [{msg: true, warning: err.message}]);
      return callback(err);
    }
    //Check for No SOAP Fault, but result code not 0
    if (result.code != 0) {
      return callback(new Error('No SOAP Fault, but result code not 0: ' + JSON.stringify(result.msg)));
    }
    //Check for No SOAP Fault, but result.msg = false (probably delete that didn't work out)
    if (result.msg === false) {
      return callback(new Error('No SOAP Fault, but result msg is false (delete failed?): ' + JSON.stringify(result.msg)));
    }
    //When resource is READY fetch the data using the resourceMethod
    if (result.msg.status === 'ERROR') {
      return callback(new Error('Error getting resource (probably incorrect x_getByObject request parameters)'));
    }
    //Check for result that should be fetched using new SOAP call
    if (typeof result.msg === 'string' || //first attempt trying if resource is READY
      result.msg.status === 'PROCESSING'  //next attempts trying if resource is READY
    ) {
      resourceId   = typeof result.msg === 'string' ? result.msg : result.msg.id;

      if (config.debug) {
        console.log('Invoking SOAP method to see if resourceId is READY: ' + resourceId);
      }
      api.resource_getById({
        uuid      : config.uuid,
        resourceId: resourceId
      }, apiCallback);
      return;
    }
    if (result.msg.status === 'READY') {
      resourceId = result.msg.id;

      if (config.debug) {
        console.log('Resource of resourceId: ' + resourceId + ' is READY ('+result.msg.size+ ' records)');
      }
      if (result.msg.size > 0) {
        api[setMethods[result.msg.type]]({
          uuid      : config.uuid,
          resourceId: resourceId,
          offset    : 0,
          size      : 50
        }, function (err, result) {
          if (err) {
            console.error('Error in getting resource set', JSON.stringify(err.stack));
          }
          callback(null, normalizeResponse(config, result));
        });
        return;
      }

      if (config.debug) {
        console.log('No records found in SOAP response');
      }
      return callback(null, []);
    }
    if (result.msg) {
      return callback(null, normalizeResponse(config, result));
    }

    return callback(new Error('Unexpected and unhandled response: ' + JSON.stringify(result.msg)));
  };
};

module.exports = Clang;<commit_msg>Error is in other property in this soap version<commit_after>var _     = require('lodash');
var soap  = require('soap');
var async = require('async');

function Clang(config) {

  if (!(this instanceof Clang)) {
    return new Clang(config);
  }
  this.config = _.clone(config || {});
  this.api    = null;
}

Clang.prototype.init = function(callback) {
  var me = this;
  if (me.config.debug) {
    console.log('Creating SOAP client');
  }

  soap.createClient('https://secure.myclang.com/app/api/soap/public/index.php?wsdl', function(err, result) {
    if (err) {
      return callback(err);
    }

    if (me.config.debug) {
      console.log('SOAP client created');
    }
    me.api = result;

    callback(null);
  });
};

Clang.prototype.request = function(methodName, args, callback) {
  var me = this;
  var localArgs;

  if (arguments.length === 2) {
    callback = args;
    localArgs = {
      uuid: me.config.uuid
    };
  } else if (arguments.length === 3) {
    localArgs = _.assign({
      uuid: me.config.uuid
    }, args || {});
  } else {
    throw new Error('request takes 3 arguments: methodName, args (object) and callback function');
  }

  if (!localArgs.uuid) {
    return setImmediate(function() {
      callback(new Error('uuid missing. Provide it with the 2nd arguments object or with client instantiation. Hint: `var clang = new Clang({uuid: \'12345678-...\'})`'));
    });
  }

  async.waterfall([
    function async_init(callback){
      if (me.api) {
        return setImmediate(callback);
      }
      me.init(callback);
    },
    function async_request(callback){
      var fn = me.api[methodName];

      if (!fn) {
        return setImmediate(function() {
          callback(new Error('Undefined method `' + methodName + '`'));
        });
      }

      fn(localArgs, buildCallback(me.config, me.api, callback));
    }
  ], callback);
};

var setMethods = {
  CUSTOMER_SET: 'customerSet_getCustomers',
  MAILING_SET : 'mailingSet_getMailings',
  OPEN_SET    : 'openSet_getOpens',
  CLICK_SET   : 'clickSet_getClicks',
  BOUNCE_SET  : 'bounceSet_getBounces'
};

var normalizeResponse = function(config, result) {
  if (result.msg === true) {
    if (config.debug) {
      console.log('SOAP success');
    }
    return [{msg: true}];
  }

  var msgKeys = Object.keys(result.msg);
  if (msgKeys.length === 0) {
    if (config.debug) {
      console.log('No records found in SOAP response');
    }
    return [];
  }
  if (msgKeys.length === 1 && result.msg[msgKeys[0]] instanceof Array) {
    if (config.debug) {
      console.log('SOAP msg array returned'); //{ code: 0, msg: { Group: [Object] } }
    }
    return result.msg[msgKeys[0]];
  }
  if (result.msg) { // 1 record from x_getById or x_create
    if (config.debug) {
      console.log('SOAP msg object returned');
    }
    return [result.msg];
  }
};

/**
 * Use this callback builder for clang method that use a resource for the dataset. It deals with:
 * - getting a resource id status
 * - getting the data set when the resource is READY
 * - normalizing the response
 * @param api - is reference to a previously created soap client with Clang's wsdl and node-soap
 * @param callback - the method for handling the final data set
 */
var buildCallback = function (config, api, callback) {
  var me = this;

  return function apiCallback(err, result) {
    /*
      first result that indicate there's a recource looks like this:  { code: 0, msg: '210577' }
      second result of fetching resource status looks like this result looks like: {
        code: 0,
        msg: {
          id    : "147082",
          type  : "CUSTOMER_SET",
          status: "READY",
          size  : "1"
        }
      }
    */
    var resourceId;
    if (err) {
      console.log('SOAP error arrived', err.body);
    }

    //Check for actual SOAP Fault generated by callback in soap/lib/client line 152
    if (err) {
      if (err.body &&
          err.body.match(/<faultcode>107<\/faultcode>/) &&
          err.body.match(/customer already member of/) )
        return callback(null, [{msg: true, warning: err.body}]);
      return callback(err.body || err.message);
    }
    //Check for No SOAP Fault, but result code not 0
    if (result.code != 0) {
      return callback(new Error('No SOAP Fault, but result code not 0: ' + JSON.stringify(result.msg)));
    }
    //Check for No SOAP Fault, but result.msg = false (probably delete that didn't work out)
    if (result.msg === false) {
      return callback(new Error('No SOAP Fault, but result msg is false (delete failed?): ' + JSON.stringify(result.msg)));
    }
    //When resource is READY fetch the data using the resourceMethod
    if (result.msg.status === 'ERROR') {
      return callback(new Error('Error getting resource (probably incorrect x_getByObject request parameters)'));
    }
    //Check for result that should be fetched using new SOAP call
    if (typeof result.msg === 'string' || //first attempt trying if resource is READY
      result.msg.status === 'PROCESSING'  //next attempts trying if resource is READY
    ) {
      resourceId   = typeof result.msg === 'string' ? result.msg : result.msg.id;

      if (config.debug) {
        console.log('Invoking SOAP method to see if resourceId is READY: ' + resourceId);
      }
      api.resource_getById({
        uuid      : config.uuid,
        resourceId: resourceId
      }, apiCallback);
      return;
    }
    if (result.msg.status === 'READY') {
      resourceId = result.msg.id;

      if (config.debug) {
        console.log('Resource of resourceId: ' + resourceId + ' is READY ('+result.msg.size+ ' records)');
      }
      if (result.msg.size > 0) {
        api[setMethods[result.msg.type]]({
          uuid      : config.uuid,
          resourceId: resourceId,
          offset    : 0,
          size      : 50
        }, function (err, result) {
          if (err) {
            console.error('Error in getting resource set', JSON.stringify(err.stack));
          }
          callback(null, normalizeResponse(config, result));
        });
        return;
      }

      if (config.debug) {
        console.log('No records found in SOAP response');
      }
      return callback(null, []);
    }
    if (result.msg) {
      return callback(null, normalizeResponse(config, result));
    }

    return callback(new Error('Unexpected and unhandled response: ' + JSON.stringify(result.msg)));
  };
};

module.exports = Clang;<|endoftext|>