<commit_before>app.controller(
    'MainController',
    [
        '$scope',
        function ($scope) {
            // placeholder
        }
    ]
);

app.controller(
    'ModalInstanceCtrl',
    function ($scope, $uibModalInstance, title, message_items) {
        $scope.title = title;
        $scope.items = message_items;

        $scope.ok = function () {
            $uibModalInstance.close(true);
        };

        $scope.cancel = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }
);

app.controller(
    'ImageSetListController',
    [
        '$scope',
        'ImageSet',
        'Species',
        'Magnification',
        'DevelopmentStage',
        'Probe',
        function ($scope, ImageSet, Species, Magnification, DevelopmentStage, Probe) {
            $scope.species = [];
            $scope.magnifications = [];
            $scope.development_stages = [];
            $scope.probes = [];
            $scope.image_sets = [];
            $scope.retrieving_data = false;

            var species = Species.query();
            species.$promise.then(function (data) {
                data.forEach(function (s) {
                    $scope.species.push(
                        {
                            'name': s,
                            'query': false
                        }
                    )
                });
            });

            var magnifications = Magnification.query();
            magnifications.$promise.then(function (data) {
                data.forEach(function (m) {
                    $scope.magnifications.push(
                        {
                            'name': m,
                            'query': false
                        }
                    )
                });
            });

            var development_stages = DevelopmentStage.query();
            development_stages.$promise.then(function (data) {
                data.forEach(function (d) {
                    $scope.development_stages.push(
                        {
                            'name': d,
                            'query': false
                        }
                    )
                });
            });

            var probes = Probe.query();
            probes.$promise.then(function (data) {
                data.forEach(function (p) {
                    $scope.probes.push(
                        {
                            'id': p.id,
                            'name': p.label,
                            'query': false
                        }
                    )
                });
            });

            $scope.filter_image_sets = function () {
                $scope.retrieving_data = true;
                $scope.image_sets = [];

                var species_filters = [];
                $scope.species.forEach(function (s) {
                    if (s.query) {
                        species_filters.push(s.name);
                    }
                });

                var mag_filters = [];
                $scope.magnifications.forEach(function (m) {
                    if (m.query) {
                        mag_filters.push(m.name);
                    }
                });

                var dev_stage_filters = [];
                $scope.development_stages.forEach(function (d) {
                    if (d.query) {
                        dev_stage_filters.push(d.name);
                    }
                });

                var probe_filters = [];
                $scope.probes.forEach(function (p) {
                    if (p.query) {
                        probe_filters.push(p.id);
                    }
                });

                $scope.image_sets = ImageSet.query(
                    {
                        'species': species_filters,
                        'magnification': mag_filters,
                        'development_stage': dev_stage_filters,
                        'probe': probe_filters
                    }
                );

                $scope.image_sets.$promise.then(function (data) {
                    $scope.retrieving_data = false;
                }, function (error) {
                    $scope.retrieving_data = false;
                });
            };
        }
    ]
);

app.controller(
    'ImageSetDetailController',
    [
        '$scope',
        '$q',
        '$routeParams',
        '$uibModal',
        'ImageSet',
        'Image',
        'Subregion',
        'AnatomyProbeMap',
        'Classify',
        'TrainModel',
        function ($scope, $q, $routeParams, $uibModal, ImageSet, Image,
                  Subregion, AnatomyProbeMap, Classify, TrainModel) {
            $scope.images = [];
            $scope.selected_image = null;
            $scope.selected_classification = null;
            $scope.mode = 'train';  // can be 'train', or 'classify'

            // drw-poly vars
            $scope.enabled = false;
            $scope.regions = {
                'svg': []
            };
            $scope.poly_height = 997;
            $scope.poly_width = 997;

            // modal setup
            $scope.modal_title = null;
            $scope.modal_items = null;
            $scope.animationsEnabled = true;
            $scope.open_modal = function (size, template_type, confirm_callback) {
                var template_url;

                if (template_type === 'confirm') {
                    template_url = 'static/ng-app/partials/confirm-modal.html';
                } else {
                    template_url = 'static/ng-app/partials/generic-modal.html';
                }

                var modalInstance = $uibModal.open(
                    {
                        animation: $scope.animationsEnabled,
                        templateUrl: template_url,
                        controller: 'ModalInstanceCtrl',
                        size: size,
                        resolve: {
                            title: function() {
                                return $scope.modal_title;
                            },
                            message_items: function () {
                                return $scope.modal_items;
                            }
                        }
                    }
                );

                modalInstance.result.then(function (selectedItem) {
                    if (selectedItem && confirm_callback != undefined) {
                        confirm_callback();
                    }
                });
            };

            $scope.launch_info_modal = function() {
                $scope.modal_title = 'How to Use the Segmentation Tool';
                $scope.modal_items = [
                    "- If training, ensure that an anatomical structure is selected from the drop down menu",
                    "- Using the mouse, left-click around the anatomical structure you are segmenting",
                    "- Lines connecting the points will automatically be drawn",
                    "- If you make a mistake, use the right-click button to remove a point",
                    "- You can also left-click, hold, and drag points to manipulate their placement",
                    "- Once finished, simply hit return and focus will be taken away from the created polygon",
                    "- Now, you can begin segmenting another structure (following the same procedure as above)",
                    "- Or, if you have segmented all subregions, you can click the 'Save Regions' button when training",
                    "- If classifing regions click 'Classify Region' when segmentation is complete"
                ];
                $scope.open_modal();
            };

            $scope.image_set = ImageSet.get({'image_set_id': $routeParams.image_set_id});

            $scope.image_set.$promise.then(function(data) {
                $scope.images = Image.query({'image_set': data.id});
                var anatomy_promises = [];

                data.probes.forEach(function(probe) {
                    anatomy_promises.push(AnatomyProbeMap.query(
                        {
                            'probe': probe.probe
                        }).$promise
                    );
                });

                $q.all(anatomy_promises).then(function(results) {
                    $scope.anatomies = [];

                    results.forEach(function(anatomy_probe_map) {
                        anatomy_probe_map.forEach(function(anatomy_probe) {
                            $scope.anatomies.push(
                                {
                                    'id': anatomy_probe.anatomy,
                                    'name': anatomy_probe.anatomy_name
                                }
                            );
                        });
                    });
                });
            });

            $scope.image_selected = function(img) {
                $scope.selected_image = img;
                if (!img.image_orig_sha1) {
                    var save_response = Image.get(
                        {
                            'id': img.id
                        },
                        {}
                    );

                    save_response.$promise.then(function(data) {
                        $scope.selected_image = data;
                        $scope.select_classification($scope.selected_classification);
                    });
                } else {
                    $scope.select_classification($scope.selected_classification);
                }
            };

            $scope.select_classification = function(classification) {
                $scope.selected_classification = classification;

                if ($scope.selected_classification === null) {
                    return false;
                }

                var existing_sub_regions = Subregion.query(
                    {
                        'image': $scope.selected_image.id,
                        'anatomy': classification.id
                    }
                );

                var new_regions = [];
                var new_region_points =[];

                existing_sub_regions.$promise.then(function(data) {
                    data.forEach(function(region) {
                        // empty array for our new region
                        new_region_points = [];

                        region.points.forEach(function(p) {
                            new_region_points.push(
                                [
                                    p.x,
                                    p.y
                                ]
                            );
                        });

                        new_regions.push(new_region_points);
                    });

                    if (new_regions.length > 0 || $scope.image_set.trainedmodel !== null) {
                        $scope.regions.svg = new_regions;
                        $scope.enabled = false;
                        $scope.displaying_saved_regions = true;
                    } else {
                        $scope.regions.svg = [];
                        $scope.enabled = true;
                        $scope.displaying_saved_regions = false;
                    }
                });
            };

            $scope.set_mode = function (mode) {
                $scope.mode = mode;
                $scope.regions.svg = [];

                if (mode === 'classify') {
                    $scope.enabled = true;
                } else if (mode === 'train') {
                    if ($scope.selected_classification !== null) {
                        $scope.select_classification($scope.selected_classification);
                    } else {
                        $scope.enabled = false;
                    }
                } else {
                    $scope.enabled = false;
                }
            };

            $scope.post_regions = function () {
                // will post all the regions for this classification in bulk,
                // since there cannot be any existing regions for the image / class combo.
                var regions = [];

                if ($scope.regions.svg.length < 4) {
                    $scope.modal_title = 'Error';
                    $scope.modal_items = [
                        'A minimum of 4 items per class must be drawn'
                    ];
                    $scope.open_modal();
                } else {
                    $scope.regions.svg.forEach(function(p) {
                        var region = {};
                        var region_points = [];

                        //Get points
                        for (var i = 0; i < p.length; i++) {
                            region_points.push(
                                {
                                    "x": p[i][0],
                                    "y": p[i][1],
                                    "order": i
                                }
                            );
                        }

                        region.anatomy = $scope.selected_classification.id;
                        region.image = $scope.selected_image.id;
                        region.points = region_points;

                        regions.push(region)
                    });

                    // How to get results of post to conditionally get ready for next
                    var post_region_response = Subregion.save(regions);

                    var new_regions = [];
                    var new_region_points =[];

                    post_region_response.$promise.then(function(data) {
                        data.forEach(function(region) {
                            // empty array for our new region
                            new_region_points = [];

                            region.points.forEach(function(p) {
                                new_region_points.push(
                                    [
                                        p.x,
                                        p.y
                                    ]
                                );
                            });

                            new_regions.push(new_region_points);
                        });

                        if (new_regions.length > 0) {
                            $scope.regions.svg = new_regions;
                            $scope.enabled = false;
                            $scope.displaying_saved_regions = true;
                            $scope.image_set = ImageSet.get(
                                {
                                    'image_set_id': $routeParams.image_set_id
                                }
                            );
                        }
                    }, function (error) {
                        $scope.modal_title = 'Error';
                        $scope.modal_items = ['An error occured when attempting to save regions'];
                        $scope.open_modal();
                    });
                }
            };

            $scope.delete_saved_regions = function () {
                var delete_response = Subregion.delete({
                    'image': $scope.selected_image.id,
                    'anatomy': $scope.selected_classification.id
                });

                delete_response.$promise.then(function (data) {
                    // update the image set to refresh the region counts
                    var image_set_response = $scope.image_set = ImageSet.get(
                        {
                            'image_set_id': $routeParams.image_set_id
                        }
                    );

                    image_set_response.$promise.then(function (image_set_data) {
                        // reset mode to clear regions
                        $scope.set_mode($scope.mode);
                    });
                }, function (error) {
                    $scope.modal_title = 'Error';
                    $scope.modal_items = [error.data['detail']];
                    $scope.open_modal();
                });
            };

            $scope.train_model = function () {
                var response = TrainModel.save(
                    {
                        'imageset': $scope.image_set.id
                    }
                );

                response.$promise.then(function (data) {
                    $scope.image_set = ImageSet.get(
                        {
                            'image_set_id': $routeParams.image_set_id
                        }
                    );
                });
            };

            $scope.launch_delete_trained_model_modal = function() {
                $scope.modal_title = 'Delete Trained Model?';
                $scope.modal_items = ['Are you sure you want to delete this trained model?'];
                $scope.open_modal('md', 'confirm', delete_trained_model);
            };

            function delete_trained_model() {
                var response = TrainModel.delete(
                    {
                        'id': $scope.image_set.trainedmodel
                    }
                );

                response.$promise.then(function (data) {
                    $scope.image_set = ImageSet.get(
                        {
                            'image_set_id': $routeParams.image_set_id
                        }
                    );
                });
            }

            $scope.classify_region = function () {
                var classify_promises = [];

                $scope.regions.svg.forEach(function (region) {
                    var payload = {};
                    var points = [];

                    //Get points
                    for (var i = 0; i < region.length; i++) {
                        points.push(
                            {
                                "x": region[i][0],
                                "y": region[i][1],
                                "order": i
                            }
                        );
                    }
                    payload.image_id = $scope.selected_image.id;
                    payload.points = points;

                    // How to get results of post to conditionally get ready for next
                    classify_promises.push(Classify.save(payload).$promise);
                });

                $q.all(classify_promises).then(function (results) {
                    $scope.modal_title = 'Classification Results';
                    $scope.modal_items = [];
                    results[0].results.forEach(function(r) {
                        $scope.modal_items.push(Object.keys(r)[0] + ': ' + (r[Object.keys(r)[0]] * 100).toFixed(2) + '%');
                    });
                    $scope.open_modal();
                });
            }
        }
    ]
);
<commit_msg>BUGFIX: don't display duplicate anatomical structures in drop-down list<commit_after>app.controller(
    'MainController',
    [
        '$scope',
        function ($scope) {
            // placeholder
        }
    ]
);

app.controller(
    'ModalInstanceCtrl',
    function ($scope, $uibModalInstance, title, message_items) {
        $scope.title = title;
        $scope.items = message_items;

        $scope.ok = function () {
            $uibModalInstance.close(true);
        };

        $scope.cancel = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }
);

app.controller(
    'ImageSetListController',
    [
        '$scope',
        'ImageSet',
        'Species',
        'Magnification',
        'DevelopmentStage',
        'Probe',
        function ($scope, ImageSet, Species, Magnification, DevelopmentStage, Probe) {
            $scope.species = [];
            $scope.magnifications = [];
            $scope.development_stages = [];
            $scope.probes = [];
            $scope.image_sets = [];
            $scope.retrieving_data = false;

            var species = Species.query();
            species.$promise.then(function (data) {
                data.forEach(function (s) {
                    $scope.species.push(
                        {
                            'name': s,
                            'query': false
                        }
                    )
                });
            });

            var magnifications = Magnification.query();
            magnifications.$promise.then(function (data) {
                data.forEach(function (m) {
                    $scope.magnifications.push(
                        {
                            'name': m,
                            'query': false
                        }
                    )
                });
            });

            var development_stages = DevelopmentStage.query();
            development_stages.$promise.then(function (data) {
                data.forEach(function (d) {
                    $scope.development_stages.push(
                        {
                            'name': d,
                            'query': false
                        }
                    )
                });
            });

            var probes = Probe.query();
            probes.$promise.then(function (data) {
                data.forEach(function (p) {
                    $scope.probes.push(
                        {
                            'id': p.id,
                            'name': p.label,
                            'query': false
                        }
                    )
                });
            });

            $scope.filter_image_sets = function () {
                $scope.retrieving_data = true;
                $scope.image_sets = [];

                var species_filters = [];
                $scope.species.forEach(function (s) {
                    if (s.query) {
                        species_filters.push(s.name);
                    }
                });

                var mag_filters = [];
                $scope.magnifications.forEach(function (m) {
                    if (m.query) {
                        mag_filters.push(m.name);
                    }
                });

                var dev_stage_filters = [];
                $scope.development_stages.forEach(function (d) {
                    if (d.query) {
                        dev_stage_filters.push(d.name);
                    }
                });

                var probe_filters = [];
                $scope.probes.forEach(function (p) {
                    if (p.query) {
                        probe_filters.push(p.id);
                    }
                });

                $scope.image_sets = ImageSet.query(
                    {
                        'species': species_filters,
                        'magnification': mag_filters,
                        'development_stage': dev_stage_filters,
                        'probe': probe_filters
                    }
                );

                $scope.image_sets.$promise.then(function (data) {
                    $scope.retrieving_data = false;
                }, function (error) {
                    $scope.retrieving_data = false;
                });
            };
        }
    ]
);

app.controller(
    'ImageSetDetailController',
    [
        '$scope',
        '$q',
        '$routeParams',
        '$uibModal',
        'ImageSet',
        'Image',
        'Subregion',
        'AnatomyProbeMap',
        'Classify',
        'TrainModel',
        function ($scope, $q, $routeParams, $uibModal, ImageSet, Image,
                  Subregion, AnatomyProbeMap, Classify, TrainModel) {
            $scope.images = [];
            $scope.selected_image = null;
            $scope.selected_classification = null;
            $scope.mode = 'train';  // can be 'train', or 'classify'

            // drw-poly vars
            $scope.enabled = false;
            $scope.regions = {
                'svg': []
            };
            $scope.poly_height = 997;
            $scope.poly_width = 997;

            // modal setup
            $scope.modal_title = null;
            $scope.modal_items = null;
            $scope.animationsEnabled = true;
            $scope.open_modal = function (size, template_type, confirm_callback) {
                var template_url;

                if (template_type === 'confirm') {
                    template_url = 'static/ng-app/partials/confirm-modal.html';
                } else {
                    template_url = 'static/ng-app/partials/generic-modal.html';
                }

                var modalInstance = $uibModal.open(
                    {
                        animation: $scope.animationsEnabled,
                        templateUrl: template_url,
                        controller: 'ModalInstanceCtrl',
                        size: size,
                        resolve: {
                            title: function() {
                                return $scope.modal_title;
                            },
                            message_items: function () {
                                return $scope.modal_items;
                            }
                        }
                    }
                );

                modalInstance.result.then(function (selectedItem) {
                    if (selectedItem && confirm_callback != undefined) {
                        confirm_callback();
                    }
                });
            };

            $scope.launch_info_modal = function() {
                $scope.modal_title = 'How to Use the Segmentation Tool';
                $scope.modal_items = [
                    "- If training, ensure that an anatomical structure is selected from the drop down menu",
                    "- Using the mouse, left-click around the anatomical structure you are segmenting",
                    "- Lines connecting the points will automatically be drawn",
                    "- If you make a mistake, use the right-click button to remove a point",
                    "- You can also left-click, hold, and drag points to manipulate their placement",
                    "- Once finished, simply hit return and focus will be taken away from the created polygon",
                    "- Now, you can begin segmenting another structure (following the same procedure as above)",
                    "- Or, if you have segmented all subregions, you can click the 'Save Regions' button when training",
                    "- If classifing regions click 'Classify Region' when segmentation is complete"
                ];
                $scope.open_modal();
            };

            $scope.image_set = ImageSet.get({'image_set_id': $routeParams.image_set_id});

            $scope.image_set.$promise.then(function(data) {
                $scope.images = Image.query({'image_set': data.id});
                var anatomy_promises = [];

                data.probes.forEach(function(probe) {
                    anatomy_promises.push(AnatomyProbeMap.query(
                        {
                            'probe': probe.probe
                        }).$promise
                    );
                });

                $q.all(anatomy_promises).then(function(results) {
                    $scope.anatomies = [];
                    var anatomy_keys = [];

                    results.forEach(function(anatomy_probe_map) {
                        anatomy_probe_map.forEach(function(anatomy_probe) {
                            if (anatomy_keys.indexOf(anatomy_probe.anatomy) === -1) {
                                anatomy_keys.push(anatomy_probe.anatomy);

                                $scope.anatomies.push(
                                    {
                                        'id': anatomy_probe.anatomy,
                                        'name': anatomy_probe.anatomy_name
                                    }
                                );
                            }
                        });
                    });
                });
            });

            $scope.image_selected = function(img) {
                $scope.selected_image = img;
                if (!img.image_orig_sha1) {
                    var save_response = Image.get(
                        {
                            'id': img.id
                        },
                        {}
                    );

                    save_response.$promise.then(function(data) {
                        $scope.selected_image = data;
                        $scope.select_classification($scope.selected_classification);
                    });
                } else {
                    $scope.select_classification($scope.selected_classification);
                }
            };

            $scope.select_classification = function(classification) {
                $scope.selected_classification = classification;

                if ($scope.selected_classification === null) {
                    return false;
                }

                var existing_sub_regions = Subregion.query(
                    {
                        'image': $scope.selected_image.id,
                        'anatomy': classification.id
                    }
                );

                var new_regions = [];
                var new_region_points =[];

                existing_sub_regions.$promise.then(function(data) {
                    data.forEach(function(region) {
                        // empty array for our new region
                        new_region_points = [];

                        region.points.forEach(function(p) {
                            new_region_points.push(
                                [
                                    p.x,
                                    p.y
                                ]
                            );
                        });

                        new_regions.push(new_region_points);
                    });

                    if (new_regions.length > 0 || $scope.image_set.trainedmodel !== null) {
                        $scope.regions.svg = new_regions;
                        $scope.enabled = false;
                        $scope.displaying_saved_regions = true;
                    } else {
                        $scope.regions.svg = [];
                        $scope.enabled = true;
                        $scope.displaying_saved_regions = false;
                    }
                });
            };

            $scope.set_mode = function (mode) {
                $scope.mode = mode;
                $scope.regions.svg = [];

                if (mode === 'classify') {
                    $scope.enabled = true;
                } else if (mode === 'train') {
                    if ($scope.selected_classification !== null) {
                        $scope.select_classification($scope.selected_classification);
                    } else {
                        $scope.enabled = false;
                    }
                } else {
                    $scope.enabled = false;
                }
            };

            $scope.post_regions = function () {
                // will post all the regions for this classification in bulk,
                // since there cannot be any existing regions for the image / class combo.
                var regions = [];

                if ($scope.regions.svg.length < 4) {
                    $scope.modal_title = 'Error';
                    $scope.modal_items = [
                        'A minimum of 4 items per class must be drawn'
                    ];
                    $scope.open_modal();
                } else {
                    $scope.regions.svg.forEach(function(p) {
                        var region = {};
                        var region_points = [];

                        //Get points
                        for (var i = 0; i < p.length; i++) {
                            region_points.push(
                                {
                                    "x": p[i][0],
                                    "y": p[i][1],
                                    "order": i
                                }
                            );
                        }

                        region.anatomy = $scope.selected_classification.id;
                        region.image = $scope.selected_image.id;
                        region.points = region_points;

                        regions.push(region)
                    });

                    // How to get results of post to conditionally get ready for next
                    var post_region_response = Subregion.save(regions);

                    var new_regions = [];
                    var new_region_points =[];

                    post_region_response.$promise.then(function(data) {
                        data.forEach(function(region) {
                            // empty array for our new region
                            new_region_points = [];

                            region.points.forEach(function(p) {
                                new_region_points.push(
                                    [
                                        p.x,
                                        p.y
                                    ]
                                );
                            });

                            new_regions.push(new_region_points);
                        });

                        if (new_regions.length > 0) {
                            $scope.regions.svg = new_regions;
                            $scope.enabled = false;
                            $scope.displaying_saved_regions = true;
                            $scope.image_set = ImageSet.get(
                                {
                                    'image_set_id': $routeParams.image_set_id
                                }
                            );
                        }
                    }, function (error) {
                        $scope.modal_title = 'Error';
                        $scope.modal_items = ['An error occured when attempting to save regions'];
                        $scope.open_modal();
                    });
                }
            };

            $scope.delete_saved_regions = function () {
                var delete_response = Subregion.delete({
                    'image': $scope.selected_image.id,
                    'anatomy': $scope.selected_classification.id
                });

                delete_response.$promise.then(function (data) {
                    // update the image set to refresh the region counts
                    var image_set_response = $scope.image_set = ImageSet.get(
                        {
                            'image_set_id': $routeParams.image_set_id
                        }
                    );

                    image_set_response.$promise.then(function (image_set_data) {
                        // reset mode to clear regions
                        $scope.set_mode($scope.mode);
                    });
                }, function (error) {
                    $scope.modal_title = 'Error';
                    $scope.modal_items = [error.data['detail']];
                    $scope.open_modal();
                });
            };

            $scope.train_model = function () {
                var response = TrainModel.save(
                    {
                        'imageset': $scope.image_set.id
                    }
                );

                response.$promise.then(function (data) {
                    $scope.image_set = ImageSet.get(
                        {
                            'image_set_id': $routeParams.image_set_id
                        }
                    );
                });
            };

            $scope.launch_delete_trained_model_modal = function() {
                $scope.modal_title = 'Delete Trained Model?';
                $scope.modal_items = ['Are you sure you want to delete this trained model?'];
                $scope.open_modal('md', 'confirm', delete_trained_model);
            };

            function delete_trained_model() {
                var response = TrainModel.delete(
                    {
                        'id': $scope.image_set.trainedmodel
                    }
                );

                response.$promise.then(function (data) {
                    $scope.image_set = ImageSet.get(
                        {
                            'image_set_id': $routeParams.image_set_id
                        }
                    );
                });
            }

            $scope.classify_region = function () {
                var classify_promises = [];

                $scope.regions.svg.forEach(function (region) {
                    var payload = {};
                    var points = [];

                    //Get points
                    for (var i = 0; i < region.length; i++) {
                        points.push(
                            {
                                "x": region[i][0],
                                "y": region[i][1],
                                "order": i
                            }
                        );
                    }
                    payload.image_id = $scope.selected_image.id;
                    payload.points = points;

                    // How to get results of post to conditionally get ready for next
                    classify_promises.push(Classify.save(payload).$promise);
                });

                $q.all(classify_promises).then(function (results) {
                    $scope.modal_title = 'Classification Results';
                    $scope.modal_items = [];
                    results[0].results.forEach(function(r) {
                        $scope.modal_items.push(Object.keys(r)[0] + ': ' + (r[Object.keys(r)[0]] * 100).toFixed(2) + '%');
                    });
                    $scope.open_modal();
                });
            }
        }
    ]
);
<|endoftext|>


<commit_before>// old-style core JSROOT main script
// temporary introduced here to support older JSROOT application
// will be removed with JSROOT v 6.2

"use strict";

if ((typeof document === "undefined") || (typeof window === "undefined")) {
   throw Error("JSRootCore.js can only be used with web browser")
}

(function() {

   function loadCoreScript(path) {
      let element = document.createElement("script");
      element.setAttribute('type', "text/javascript");
      element.setAttribute('src', path);

      return new Promise(resolveFunc => {
         element.onload = function() {
            element.onload = null;
            resolveFunc();
         }
         document.getElementsByTagName("head")[0].appendChild(element);
      })
   }

   let source_fullpath = document.currentScript.src;
   let minified = source_fullpath.indexOf("JSRootCore.min.js") >= 0;
   let p0 = source_fullpath.indexOf("JSRootCore.");
   let path0 = (p0>=0) ? source_fullpath.substr(0, p0) : "./";
   let _redirects = [];

   loadCoreScript(path0 + "JSRoot.core" + (minified ? ".min.js" : ".js")).then(() => {

      if (!JSROOT)
         throw Error("Fail to load JSRoot.core.js script from " + path0);

      let _warned = {};
      function warnOnce(msg) {
         if (!_warned[msg]) {
            console.warn(msg);
            _warned[msg] = true;
         }
      }

      JSROOT.GetUrlOption = function(opt, url, dflt) {
         warnOnce('Using obsolete JSROOT.GetUrlOption, change to JSROOT.decodeUrl');
         return JSROOT.decodeUrl(url).get(opt, dflt === undefined ? null : dflt);
      }

      JSROOT.AssertPrerequisites = function(req, callback) {
         warnOnce('Using obsolete JSROOT.AssertPrerequisites, change to JSROOT.require');
         req = req.replace(/2d;v7;/g, "v7gpad;").replace(/2d;v6;/g, "gpad;").replace(/more2d;/g, 'more;').replace(/2d;/g, 'gpad;').replace(/;v6;v7/g, ";gpad;v7gpad");
         JSROOT.require(req).then(callback);
      }

      JSROOT.OpenFile = function(filename, callback) {
         warnOnce('Using obsolete JSROOT.OpenFile function, change to JSROOT.openFile');
         let res = JSROOT.openFile(filename);
         return !callback ? res : res.then(callback);
      }

      JSROOT.JSONR_unref = function(arg) {
         warnOnce('Using obsolete JSROOT.JSONR_unref function, change to JSROOT.parse');
         return JSROOT.parse(arg);
      }

      JSROOT.MakeSVG = function(args) {
         warnOnce('Using obsolete JSROOT.MakeSVG function, change to JSROOT.makeSVG');
         return JSROOT.makeSVG(args);
      }

      JSROOT.CallBack = function(func, arg1, arg2) {
         warnOnce('Using obsolete JSROOT.CallBack function');

         if (typeof func == 'string') func = JSROOT.findFunction(func);

         if (!func) return;

         if (typeof func == 'function') return func(arg1,arg2);

         if (typeof func != 'object') return;

         if (('obj' in func) && ('func' in func) &&
            (typeof func.obj == 'object') && (typeof func.func == 'string') &&
            (typeof func.obj[func.func] == 'function')) {
                return func.obj[func.func](arg1, arg2);
         }
      }

      function window_on_load(tmout, func) {
         if (document.attachEvent ? document.readyState === 'complete' : document.readyState !== 'loading')
            return tmout ? setTimeout(func, 10) : func();

         window.onload = tmout ? () => setTimeout(func, 10) : func;
      }

      _redirects.forEach(args => {
         let name = args.shift();
         if (typeof name == 'string') {
            JSROOT[name](...args);
         } else {
            let resolve = name;
            name = args.shift();
            JSROOT[name](...args).then(resolve);
         }
      });

      let d = JSROOT.decodeUrl(source_fullpath);

      // use timestamp to overcome cache limitation
      if (d.has('nocache')) JSROOT.settings.NoCache = (new Date).getTime();
      // server may send wrong content length by partial requests, use other method to control this
      if (d.has('wrong_http_response') || JSROOT.decodeUrl().has('wrong_http_response'))
         JSROOT.settings.HandleWrongHttpResponse = true;
      // let ignore sap loader even with openui5 loaded
      if (d.has('nosap')) JSROOT._.sap = undefined;

      if (d.has('gui') || JSROOT._.amd) {
         return window_on_load(JSROOT._.amd, () => {
            let gui_elem, gui_kind;
            function testDiv(id, kind) {
               if (gui_elem) return;
               let elem = document.getElementById(id);
               if (elem) { gui_elem = elem; gui_kind = kind; }
            }
            testDiv('simpleGUI', 'gui');
            testDiv('drawGUI', 'draw');
            testDiv('onlineGUI', 'online');
            if (gui_elem) JSROOT.buildGUI(gui_elem, gui_kind);
         })
      }

      let prereq = "", user = d.get('load'), onload = d.get('onload');
      if (d.has('io')) prereq += "io;";
      if (d.has('tree')) prereq += "tree;";
      if (d.has('2d')) prereq += "gpad;";
      if (d.has('v7')) prereq += "v7gpad;";
      if (d.has('hist')) prereq += "hist;";
      if (d.has('hierarchy')) prereq += "hierarchy;";
      if (d.has('jq2d')) prereq += "jq2d;";
      if (d.has('more2d')) prereq += "more;";
      if (d.has('geom')) prereq += "geom;";
      if (d.has('3d')) prereq += "base3d;";
      if (d.has('math')) prereq += "math;";
      if (d.has('mathjax')) prereq += "mathjax;";
      if (d.has('openui5')) prereq += "openui5;";

      if (user) { prereq += "io;gpad;"; user = user.split(";"); }

      if (prereq || onload || user)
         window_on_load(false, () => JSROOT.require(prereq)
                               .then(() => JSROOT.loadScript(user))
                               .then(() => JSROOT.CallBack(onload)));
   });

   let tmpJSROOT = { _workaround: true };

   tmpJSROOT.OpenFile = function(filename, call_back) {
      if (JSROOT !== tmpJSROOT)
         JSROOT.OpenFile(filename, call_back);
      else
         _redirects.push(["OpenFile", filename, call_back]);
   }

   tmpJSROOT.openFile = function(filename) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.openFile(filename);
      return new Promise(resolve => _redirects.push([resolve, "openFile", filename]));
   }

   tmpJSROOT.draw = function(divid, obj, opt, call_back) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.draw(divid, obj, opt).then(call_back);
     _redirects.push(["draw", divid, obj, opt, call_back]);
   }

   tmpJSROOT.redraw = function(divid, obj, opt, call_back) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.redraw(divid, obj, opt).then(call_back);
     _redirects.push(["redraw", divid, obj, opt, call_back]);
   }

   // until real JSROOT is loaded, provide minimal functions
   globalThis.JSROOT = tmpJSROOT;

})();<commit_msg>Add connectWebWindow redirection<commit_after>// old-style core JSROOT main script
// temporary introduced here to support older JSROOT application
// will be removed with JSROOT v 6.2

"use strict";

if ((typeof document === "undefined") || (typeof window === "undefined")) {
   throw Error("JSRootCore.js can only be used with web browser")
}

(function() {

   function loadCoreScript(path) {
      let element = document.createElement("script");
      element.setAttribute('type', "text/javascript");
      element.setAttribute('src', path);

      return new Promise(resolveFunc => {
         element.onload = function() {
            element.onload = null;
            resolveFunc();
         }
         document.getElementsByTagName("head")[0].appendChild(element);
      })
   }

   let source_fullpath = document.currentScript.src;
   let minified = source_fullpath.indexOf("JSRootCore.min.js") >= 0;
   let p0 = source_fullpath.indexOf("JSRootCore.");
   let path0 = (p0>=0) ? source_fullpath.substr(0, p0) : "./";
   let _redirects = [];

   loadCoreScript(path0 + "JSRoot.core" + (minified ? ".min.js" : ".js")).then(() => {

      if (!JSROOT)
         throw Error("Fail to load JSRoot.core.js script from " + path0);

      let _warned = {};
      function warnOnce(msg) {
         if (!_warned[msg]) {
            console.warn(msg);
            _warned[msg] = true;
         }
      }

      JSROOT.GetUrlOption = function(opt, url, dflt) {
         warnOnce('Using obsolete JSROOT.GetUrlOption, change to JSROOT.decodeUrl');
         return JSROOT.decodeUrl(url).get(opt, dflt === undefined ? null : dflt);
      }

      JSROOT.AssertPrerequisites = function(req, callback) {
         warnOnce('Using obsolete JSROOT.AssertPrerequisites, change to JSROOT.require');
         req = req.replace(/2d;v7;/g, "v7gpad;").replace(/2d;v6;/g, "gpad;").replace(/more2d;/g, 'more;').replace(/2d;/g, 'gpad;').replace(/;v6;v7/g, ";gpad;v7gpad");
         JSROOT.require(req).then(callback);
      }

      JSROOT.OpenFile = function(filename, callback) {
         warnOnce('Using obsolete JSROOT.OpenFile function, change to JSROOT.openFile');
         let res = JSROOT.openFile(filename);
         return !callback ? res : res.then(callback);
      }

      JSROOT.JSONR_unref = function(arg) {
         warnOnce('Using obsolete JSROOT.JSONR_unref function, change to JSROOT.parse');
         return JSROOT.parse(arg);
      }

      JSROOT.MakeSVG = function(args) {
         warnOnce('Using obsolete JSROOT.MakeSVG function, change to JSROOT.makeSVG');
         return JSROOT.makeSVG(args);
      }

      JSROOT.CallBack = function(func, arg1, arg2) {
         warnOnce('Using obsolete JSROOT.CallBack function');

         if (typeof func == 'string') func = JSROOT.findFunction(func);

         if (!func) return;

         if (typeof func == 'function') return func(arg1,arg2);

         if (typeof func != 'object') return;

         if (('obj' in func) && ('func' in func) &&
            (typeof func.obj == 'object') && (typeof func.func == 'string') &&
            (typeof func.obj[func.func] == 'function')) {
                return func.obj[func.func](arg1, arg2);
         }
      }

      function window_on_load(tmout, func) {
         if (document.attachEvent ? document.readyState === 'complete' : document.readyState !== 'loading')
            return tmout ? setTimeout(func, 10) : func();

         window.onload = tmout ? () => setTimeout(func, 10) : func;
      }

      _redirects.forEach(args => {
         let name = args.shift();
         if (typeof name == 'string') {
            JSROOT[name](...args);
         } else {
            let resolve = name;
            name = args.shift();
            JSROOT[name](...args).then(resolve);
         }
      });

      let d = JSROOT.decodeUrl(source_fullpath);

      // use timestamp to overcome cache limitation
      if (d.has('nocache')) JSROOT.settings.NoCache = (new Date).getTime();
      // server may send wrong content length by partial requests, use other method to control this
      if (d.has('wrong_http_response') || JSROOT.decodeUrl().has('wrong_http_response'))
         JSROOT.settings.HandleWrongHttpResponse = true;
      // let ignore sap loader even with openui5 loaded
      if (d.has('nosap')) JSROOT._.sap = undefined;

      if (d.has('gui') || JSROOT._.amd) {
         return window_on_load(JSROOT._.amd, () => {
            let gui_elem, gui_kind;
            function testDiv(id, kind) {
               if (gui_elem) return;
               let elem = document.getElementById(id);
               if (elem) { gui_elem = elem; gui_kind = kind; }
            }
            testDiv('simpleGUI', 'gui');
            testDiv('drawGUI', 'draw');
            testDiv('onlineGUI', 'online');
            if (gui_elem) JSROOT.buildGUI(gui_elem, gui_kind);
         })
      }

      let prereq = "", user = d.get('load'), onload = d.get('onload');
      if (d.has('io')) prereq += "io;";
      if (d.has('tree')) prereq += "tree;";
      if (d.has('2d')) prereq += "gpad;";
      if (d.has('v7')) prereq += "v7gpad;";
      if (d.has('hist')) prereq += "hist;";
      if (d.has('hierarchy')) prereq += "hierarchy;";
      if (d.has('jq2d')) prereq += "jq2d;";
      if (d.has('more2d')) prereq += "more;";
      if (d.has('geom')) prereq += "geom;";
      if (d.has('3d')) prereq += "base3d;";
      if (d.has('math')) prereq += "math;";
      if (d.has('mathjax')) prereq += "mathjax;";
      if (d.has('openui5')) prereq += "openui5;";

      if (user) { prereq += "io;gpad;"; user = user.split(";"); }

      if (prereq || onload || user)
         window_on_load(false, () => JSROOT.require(prereq)
                               .then(() => JSROOT.loadScript(user))
                               .then(() => JSROOT.CallBack(onload)));
   });

   let tmpJSROOT = { _workaround: true };

   tmpJSROOT.OpenFile = function(filename, call_back) {
      if (JSROOT !== tmpJSROOT)
         JSROOT.OpenFile(filename, call_back);
      else
         _redirects.push(["OpenFile", filename, call_back]);
   }

   tmpJSROOT.openFile = function(filename) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.openFile(filename);
      return new Promise(resolve => _redirects.push([resolve, "openFile", filename]));
   }

   tmpJSROOT.draw = function(divid, obj, opt, call_back) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.draw(divid, obj, opt).then(call_back);
     _redirects.push(["draw", divid, obj, opt, call_back]);
   }

   tmpJSROOT.redraw = function(divid, obj, opt, call_back) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.redraw(divid, obj, opt).then(call_back);
     _redirects.push(["redraw", divid, obj, opt, call_back]);
   }

   tmpJSROOT.connectWebWindow = function(arg) {
      if (JSROOT !== tmpJSROOT)
         return JSROOT.connectWebWindow(arg);
      return new Promise(resolve => _redirects.push([resolve, "connectWebWindow", arg]));
   }

   // until real JSROOT is loaded, provide minimal functions
   globalThis.JSROOT = tmpJSROOT;

})();<|endoftext|>


<commit_before>F2.Apps["com_openf2_examples_javascript_chart"] = (function(){

	var app = function (appConfig, appContent, root) {
		this.symbol = "MSFT";
		this.appConfig = appConfig;
		this.appContent = appContent;
		this.ui = this.appConfig.ui;
		this.root = root;
		this.$root = $(root);
		this.$app = $("#f2-1year-chart", this.$root);
		this.CHT_CONTAINER = 'f2-1year-chart';
	};

	app.prototype.redraw = function(data) {
		this.hc = null;
		this.symbol = data.symbol;
		this.getData();
	};

	app.prototype.init = function() {

		this.getData();

		//setup container symbol change listener to draw new chart.
		F2.Events.on(F2.Constants.Events.CONTAINER_SYMBOL_CHANGE, $.proxy(function(symbolData){
				this.redraw(symbolData);
			},this)
		);
	};

	app.prototype.getData = function() {

		this.ui.showMask(this.$root,true);

		$.ajax({
			beforeSend:function () {
				this.ui.setTitle("Loading chart...");
			},
			data: {
				symbol: this.symbol,
				duration: 365  // Fixed to one year
			},
			url: 'http://dev.markitondemand.com/Api/Timeseries/jsonp',
			dataType: 'jsonp',
			context: this

		}).done(function(jqxhr,txtStatus){
			//Catch errors
			if ( !jqxhr.Data || jqxhr.Message ) {
				if ( typeof console == 'object' ) console.error('Error: ', jqxhr.Message);
				this._chartError(jqxhr);
				return;
			}
			this.HandleAPIData(jqxhr);

		}).fail(function(jqxhr,txtStatus){
			F2.log('Could not generate chart.', jqxhr);
			this._chartError(jqxhr);
		});
	};

	app.prototype._chartError = function(jqxhr) {
		F2.log("Price Chart Error", jqxhr);
		this.ui.setTitle("Chart Error");
				this.$app.html("
An error occurred loading price data for " +this.symbol+ ".
");
				this.ui.hideMask(this.$root);
				this.ui.updateHeight();
	};

	app.prototype.style = {
		fontColor: '#444444',
		fontFamily: 'Arial, sans-serif',
		fontSize: 12,
		lineHeight: 1.2
	};
	app.prototype.gridColor = '#DDDDDD';
	app.prototype.gridAltColor = '#F7F7F7';

	// Parses API data to provide HighCharts-ready data series for close values,
	// additionally deriving up/down month indicators.
	//
	app.prototype.HandleAPIData = function (json) {

		$(this.CHT_CONTAINER).empty();

		// Set up vars for first data series
		var apiDates = json.Data.SeriesDates,
			apiValues = json.Data.Series.close.values,
			closeSeriesData = [ ];

		// Translate API JSON into a HighCharts-format data series
		for ( var i = 0; i < apiDates.length; i++ ) {
			var dat = new Date(apiDates[i]);
			var dateIn = Date.UTC(dat.getFullYear(), dat.getMonth(), dat.getDate());
			var val = apiValues[i];
			closeSeriesData.push([dateIn,val]);
		}

		// Instantiate a new chart with base configuration options (everything but the data)
		var hcChartObj = new Highcharts.Chart(this.getBaselineOptions());
		hcChartObj.series[0].setData(closeSeriesData, true);  // Set close-values series data
		//hcChartObj.setTitle({ text: ('One-year price movement for ' + json.Data.Name).toUpperCase() });  // Set title
		hcChartObj.setTitle({ text:'' });

		this.ui.hideMask(this.$root);
		this.ui.setTitle("ONE-YEAR PRICE MOVEMENT FOR " + this.symbol);

		// No options setting is available for this, so force the price line to be rounded
		$('.highcharts-series path:first', this.root).attr('stroke-linejoin', 'round').attr('stroke-linecap', 'round');

		// Set up vars for up/down month data series
		var currentMonthName, currentJSDate, currentJSUTCDate, currentVal,
			upSeriesData = [ ],
			downSeriesData = [ ];
		var dataRanges = hcChartObj.yAxis[0].getExtremes();  // Will need to reset to this later
			minVal = dataRanges.min,  // Will set red/green indicators to this value
			apiValues = json.Data.Series.close.values,
			apiDates = json.Data.SeriesDates,
			firstMonthName = apiDates[0].substr(4, 3),  // First!
			prevMonthName = firstMonthName,
			prevJSDate = new Date(prevMonthName + ' 1, ' + apiDates[0].substr(-4)),
			prevJSUTCDate = Date.UTC(prevJSDate.getFullYear(), prevJSDate.getMonth(), prevJSDate.getDate()),
			prevVal = apiValues[0];

		// Now walk through all data points again (had to do it once before to get the ranges),
		// looking for month boundaries and deciding if the previous month ended up or down over
		// the preceding month's close
		for ( var i = 1; i < apiDates.length; i++ ) {
			currentMonthName = apiDates[i].substr(4, 3);
			if ( currentMonthName != prevMonthName ) {  // Into a new month in the data
				currentVal = apiValues[i - 1];  // Last close in the preceding month
				currentJSDate = new Date(currentMonthName + ' 1, ' + apiDates[i].substr(-4));
				currentJSUTCDate = Date.UTC(currentJSDate.getFullYear(), currentJSDate.getMonth(), currentJSDate.getDate());
				if ( prevMonthName != firstMonthName ) {  // Skip the first month, it's incomplete
					if ( currentVal >= prevVal ) {
						upSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
						downSeriesData.push( [ currentJSUTCDate, null ] );
					}
					else {
						downSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
						upSeriesData.push( [ currentJSUTCDate, null ] );
					}
				}
				prevVal = currentVal;
				prevMonthName = currentMonthName;
				prevJSUTCDate = currentJSUTCDate;
			}
		}
		// Add one last interval for the partial month-to-date
		currentVal = apiValues[i - 1];  // Last close value in the data
		currentJSDate = new Date(apiDates[i - 1]);
		currentJSUTCDate = Date.UTC(currentJSDate.getFullYear(), currentJSDate.getMonth(), currentJSDate.getDate());
		if ( currentVal >= prevVal ) upSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
		else downSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );

		// Add the up month/down month data to the chart's series
        if ($.browser.msie && parseInt($.browser.version) < 9) {
            //commenting out for issue #1.
            //o-do to come back and get grid lines working.
        } else {
            hcChartObj.series[1].setData(upSeriesData, false);
            hcChartObj.series[2].setData(downSeriesData, false);
        }
        hcChartObj.yAxis[0].setExtremes(dataRanges.dataMin, dataRanges.dataMax, true, false);

		this.ui.updateHeight();
	};

	// Defines the HighCharts configuration options.
	//
	app.prototype.getBaselineOptions = function () {
		return {
			chart: {
				borderColor: 'rgba(255, 255, 255, 0.0)',
				borderRadius: 0,
				defaultSeriesType: 'line',
				renderTo: this.CHT_CONTAINER,
				spacingBottom: 25,
				spacingLeft: 1,
				spacingRight: 1
			},
			credits: {
				enabled: false
			},
			legend: {
				enabled: false
			},
			plotOptions: {
				line: {
					animation: false,
					lineWidth: 3.5
				},
				series: {
					marker: {
						enabled: false
					},
					shadow: false,
					states: {
						hover: {
							enabled: false
						}
					}
				}
			},
			series: [{
				color: '#6A8F8E',
				name: 'Close price'
			},
			{
				color: '#2EA94F',
				lineWidth: 6,
				name: 'Up months'
			},
			{
				color: '#DB411C',
				lineWidth: 6,
				name: 'Down months'
			}],
			title: {
				align: 'left',
				style: {
					color: '#666',
					fontFamily: this.style.fontFamily,
					fontSize: 14,
					fontWeight: 'bold',
					lineHeight: this.style.lineHeight
				}
			},
			tooltip: {
				borderRadius: 1,
				crosshairs: true,
				formatter: function () {
					if ( this.series.name == 'Close price' ) {
						return ''
							+ Highcharts.dateFormat('%b %e %Y', this.x)
							+ '
'
							+ this.series.name + ': ' + Highcharts.numberFormat(this.y, 2)
							+ '';
					}
					else return false;
				},
				style: {
					color: this.style.fontColor,
					fontFamily: this.style.fontFamily,
					fontSize: this.style.fontSize,
					lineHeight: this.style.lineHeight,
					padding: this.style.fontSize
				}
			},
			xAxis: [{  // Bottom datetime axis (short intervals)
				dateTimeLabelFormats: {
					minute: '%l:%M%P',
					hour: '%l%P',
					day: '%a',
					day: '%b %e',
					week: '%b %e',
					month: '%b',
					year: '%Y'
				},
				gridLineDashStyle: 'shortdot',
				gridLineColor: this.gridAltColor,
				gridLineWidth: 1,
				labels: {
					align: 'left',
					style: {
						color: this.style.fontColor,
						fontFamily: this.style.fontFamily,
						fontSize: this.style.fontSize
					},
					x: (this.style.fontSize / 2),
					y: (this.style.fontSize * this.style.lineHeight * 1.5)
				},
				lineColor: this.gridColor,
				tickColor: this.gridColor,
				tickInterval: (30 * 24 * 3600 * 1000),  // One month
				tickLength: (this.style.fontSize * this.style.lineHeight * 1.5),
				type: 'datetime'
			},{  // Top datetime axis (longer intervals)
				dateTimeLabelFormats: {
					day: '%a',  // Default
					week: '%a',
					month: '%b %Y',
					year: '%Y'
				},
				gridLineWidth: 1,
				gridLineColor: this.gridColor,
				labels: {
					align: 'left',
					style: {
						color: this.style.fontColor,
						fontFamily: this.style.fontFamily,
						fontSize: this.style.fontSize
					},
					x: (this.style.fontSize / 2)
				},
				lineColor: this.gridColor,
				linkedTo: 0,
				opposite: true,
				tickColor: this.gridColor,
				tickInterval: (365 * 24 * 3600 * 1000),  // One year
				tickLength: (this.style.fontSize * this.style.lineHeight),
				type: 'datetime'
			}],
			yAxis: [{
				gridLineColor: this.gridColor,
				labels: {
					align: 'left',
					formatter: function () {
						return Highcharts.numberFormat(this.value, 2);
					},
					style: {
						color: this.style.fontColor,
						fontFamily: this.style.fontFamily,
						fontSize: this.style.fontSize
					},
					x: 0,
					y: (this.style.fontSize + 3)
				},
				maxPadding: 0,
				minPadding: 0,
				opposite: true,
				showFirstLabel: false,
				tickColor: this.gridColor,
				tickLength: 100,  // Cropped at left of chart
				tickWidth: 1,
				title: {
					text: ''
				}
			}]
		};
	};

		return app;

})();<commit_msg>Fixed #47<commit_after>F2.Apps["com_openf2_examples_javascript_chart"] = (function(){

	var app = function (appConfig, appContent, root) {
		this.symbol = "MSFT";
		this.appConfig = appConfig;
		this.appContent = appContent;
		this.ui = this.appConfig.ui;
		this.root = root;
		this.$root = $(root);
		this.$app = $("#f2-1year-chart", this.$root);
		this.CHT_CONTAINER = 'f2-1year-chart';
	};

	app.prototype.redraw = function(data) {
		this.hc = null;
		this.symbol = data.symbol;
		this.getData();
	};

	app.prototype.init = function() {

		this.getData();

		//setup container symbol change listener to draw new chart.
		F2.Events.on(F2.Constants.Events.CONTAINER_SYMBOL_CHANGE, $.proxy(function(symbolData){
				this.redraw(symbolData);
			},this)
		);
	};

	app.prototype.getData = function() {

		this.ui.showMask(this.$root,true);

		$.ajax({
			beforeSend:function () {
				this.ui.setTitle("Loading chart...");
			},
			data: {
				symbol: this.symbol,
				duration: 365  // Fixed to one year
			},
			url: 'http://dev.markitondemand.com/Api/Timeseries/jsonp',
			dataType: 'jsonp',
			context: this

		}).done(function(jqxhr,txtStatus){
			//Catch errors
			if ( !jqxhr.Data || jqxhr.Message ) {
				if ( typeof console == 'object' ) console.error('Error: ', jqxhr.Message);
				this._chartError(jqxhr);
				return;
			}
			this.HandleAPIData(jqxhr);

		}).fail(function(jqxhr,txtStatus){
			F2.log('Could not generate chart.', jqxhr);
			this._chartError(jqxhr);
		});
	};

	app.prototype._chartError = function(jqxhr) {
		F2.log("Price Chart Error", jqxhr);
		this.ui.setTitle("Chart Error");
				this.$app.html("
An error occurred loading price data for " +this.symbol+ ".
");
				this.ui.hideMask(this.$root);
				this.ui.updateHeight();
	};

	app.prototype.style = {
		fontColor: '#444444',
		fontFamily: 'Arial, sans-serif',
		fontSize: 12,
		lineHeight: 1.2
	};
	app.prototype.gridColor = '#DDDDDD';
	app.prototype.gridAltColor = '#F7F7F7';

	// Parses API data to provide HighCharts-ready data series for close values,
	// additionally deriving up/down month indicators.
	//
	app.prototype.HandleAPIData = function (json) {

		$(this.CHT_CONTAINER).empty();

		// Set up vars for first data series
		var apiDates = json.Data.SeriesDates,
			apiValues = json.Data.Series.close.values,
			closeSeriesData = [ ];

		// Translate API JSON into a HighCharts-format data series
		for ( var i = 0; i < apiDates.length; i++ ) {
			var dat = new Date(apiDates[i]);
			var dateIn = Date.UTC(dat.getFullYear(), dat.getMonth(), dat.getDate());
			var val = apiValues[i];
			closeSeriesData.push([dateIn,val]);
		}

		// Instantiate a new chart with base configuration options (everything but the data)
		var hcChartObj = new Highcharts.Chart(this.getBaselineOptions());
		hcChartObj.series[0].setData(closeSeriesData, true);  // Set close-values series data
		//hcChartObj.setTitle({ text: ('One-year price movement for ' + json.Data.Name).toUpperCase() });  // Set title
		hcChartObj.setTitle({ text:'' });

		this.ui.hideMask(this.$root);
		this.ui.setTitle("ONE-YEAR PRICE MOVEMENT FOR " + this.symbol);

		// No options setting is available for this, so force the price line to be rounded
		$('.highcharts-series path:first', this.root).attr('stroke-linejoin', 'round').attr('stroke-linecap', 'round');

		// Set up vars for up/down month data series
		var currentMonthName, currentJSDate, currentJSUTCDate, currentVal,
			upSeriesData = [ ],
			downSeriesData = [ ];
		var dataRanges = hcChartObj.yAxis[0].getExtremes();  // Will need to reset to this later
			minVal = dataRanges.min,  // Will set red/green indicators to this value
			apiValues = json.Data.Series.close.values,
			apiDates = json.Data.SeriesDates,
			firstMonthName = apiDates[0].substr(4, 3),  // First!
			prevMonthName = firstMonthName,
			prevJSDate = new Date(prevMonthName + ' 1, ' + apiDates[0].substr(-4)),
			prevJSUTCDate = Date.UTC(prevJSDate.getFullYear(), prevJSDate.getMonth(), prevJSDate.getDate()),
			prevVal = apiValues[0];

		// Now walk through all data points again (had to do it once before to get the ranges),
		// looking for month boundaries and deciding if the previous month ended up or down over
		// the preceding month's close
		for ( var i = 1; i < apiDates.length; i++ ) {
			currentMonthName = apiDates[i].substr(4, 3);
			if ( currentMonthName != prevMonthName ) {  // Into a new month in the data
				currentVal = apiValues[i - 1];  // Last close in the preceding month
				currentJSDate = new Date(currentMonthName + ' 1, ' + apiDates[i].substr(-4));
				currentJSUTCDate = Date.UTC(currentJSDate.getFullYear(), currentJSDate.getMonth(), currentJSDate.getDate());
				if ( prevMonthName != firstMonthName ) {  // Skip the first month, it's incomplete
					if ( currentVal >= prevVal ) {
						upSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
						downSeriesData.push( [ currentJSUTCDate, null ] );
					}
					else {
						downSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
						upSeriesData.push( [ currentJSUTCDate, null ] );
					}
				}
				prevVal = currentVal;
				prevMonthName = currentMonthName;
				prevJSUTCDate = currentJSUTCDate;
			}
		}
		// Add one last interval for the partial month-to-date
		currentVal = apiValues[i - 1];  // Last close value in the data
		currentJSDate = new Date(apiDates[i - 1]);
		currentJSUTCDate = Date.UTC(currentJSDate.getFullYear(), currentJSDate.getMonth(), currentJSDate.getDate());
		if ( currentVal >= prevVal ) upSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );
		else downSeriesData.push( [ prevJSUTCDate, minVal ], [ currentJSUTCDate, minVal ] );

		// Add the up month/down month data to the chart's series
        hcChartObj.series[1].setData(upSeriesData, false);
        hcChartObj.series[2].setData(downSeriesData, false);

        hcChartObj.yAxis[0].setExtremes(dataRanges.dataMin, dataRanges.dataMax, true, false);

		this.ui.updateHeight();
	};

	// Defines the HighCharts configuration options.
	//
	app.prototype.getBaselineOptions = function () {
		return {
			chart: {
				borderColor: 'rgba(255, 255, 255, 0.0)',
				borderRadius: 0,
				defaultSeriesType: 'line',
				renderTo: this.CHT_CONTAINER,
				spacingBottom: 25,
				spacingLeft: 1,
				spacingRight: 1
			},
			credits: {
				enabled: false
			},
			legend: {
				enabled: false
			},
			plotOptions: {
				line: {
					animation: false,
					lineWidth: 3.5
				},
				series: {
					marker: {
						enabled: false
					},
					shadow: false,
					states: {
						hover: {
							enabled: false
						}
					}
				}
			},
			series: [{
				color: '#6A8F8E',
				name: 'Close price'
			},
			{
				color: '#2EA94F',
				lineWidth: 6,
				name: 'Up months'
			},
			{
				color: '#DB411C',
				lineWidth: 6,
				name: 'Down months'
			}],
			title: {
				align: 'left',
				style: {
					color: '#666',
					fontFamily: this.style.fontFamily,
					fontSize: 14,
					fontWeight: 'bold',
					lineHeight: this.style.lineHeight
				}
			},
			tooltip: {
				borderRadius: 1,
				crosshairs: true,
				formatter: function () {
					if ( this.series.name == 'Close price' ) {
						return ''
							+ Highcharts.dateFormat('%b %e %Y', this.x)
							+ '
'
							+ this.series.name + ': ' + Highcharts.numberFormat(this.y, 2)
							+ '';
					}
					else return false;
				},
				style: {
					color: this.style.fontColor,
					fontFamily: this.style.fontFamily,
					fontSize: this.style.fontSize,
					lineHeight: this.style.lineHeight,
					padding: this.style.fontSize
				}
			},
			xAxis: [{  // Bottom datetime axis (short intervals)
				dateTimeLabelFormats: {
					minute: '%l:%M%P',
					hour: '%l%P',
					day: '%a',
					day: '%b %e',
					week: '%b %e',
					month: '%b',
					year: '%Y'
				},
				gridLineDashStyle: 'shortdot',
				gridLineColor: this.gridAltColor,
				gridLineWidth: 1,
				labels: {
					align: 'left',
					style: {
						color: this.style.fontColor,
						fontFamily: this.style.fontFamily,
						fontSize: this.style.fontSize
					},
					x: (this.style.fontSize / 2),
					y: (this.style.fontSize * this.style.lineHeight * 1.5)
				},
				lineColor: this.gridColor,
				tickColor: this.gridColor,
				tickInterval: (30 * 24 * 3600 * 1000),  // One month
				tickLength: (this.style.fontSize * this.style.lineHeight * 1.5),
				type: 'datetime'
			},{  // Top datetime axis (longer intervals)
				dateTimeLabelFormats: {
					day: '%a',  // Default
					week: '%a',
					month: '%b %Y',
					year: '%Y'
				},
				gridLineWidth: 1,
				gridLineColor: this.gridColor,
				labels: {
					align: 'left',
					style: {
						color: this.style.fontColor,
						fontFamily: this.style.fontFamily,
						fontSize: this.style.fontSize
					},
					x: (this.style.fontSize / 2)
				},
				lineColor: this.gridColor,
				linkedTo: 0,
				opposite: true,
				tickColor: this.gridColor,
				tickInterval: (365 * 24 * 3600 * 1000),  // One year
				tickLength: (this.style.fontSize * this.style.lineHeight),
				type: 'datetime'
			}],
			yAxis: [{
				gridLineColor: this.gridColor,
				labels: {
					align: 'left',
					formatter: function () {
						return Highcharts.numberFormat(this.value, 2);
					},
					style: {
						color: this.style.fontColor,
						fontFamily: this.style.fontFamily,
						fontSize: this.style.fontSize
					},
					x: 0,
					y: (this.style.fontSize + 3)
				},
				maxPadding: 0,
				minPadding: 0,
				opposite: true,
				showFirstLabel: false,
				tickColor: this.gridColor,
				tickLength: 100,  // Cropped at left of chart
				tickWidth: 1,
				title: {
					text: ''
				}
			}]
		};
	};

		return app;

})();<|endoftext|>


<commit_before>module("misc", {
  setup : function () {
    var dbname = location.search.match(/[?&]dbname=([^&]+)/);
    this.name = dbname && decodeURIComponent(dbname[1]);
  }
});

asyncTest("Add a doc", 2, function() {
  openTestDB(this.name, function(err, db) {
    ok(!err, 'opened the pouch');
    db.post({test:"somestuff"}, function (err, info) {
      ok(!err, 'saved a doc with post');
      start();
    });
  });
});
<commit_msg>(#416) - Fix lint errors in postTest.js<commit_after>/*globals openTestDB: false */

"use strict";

module("misc", {
  setup : function () {
    var dbname = location.search.match(/[?&]dbname=([^&]+)/);
    this.name = dbname && decodeURIComponent(dbname[1]);
  }
});

asyncTest("Add a doc", 2, function() {
  openTestDB(this.name, function(err, db) {
    ok(!err, 'opened the pouch');
    db.post({test:"somestuff"}, function (err, info) {
      ok(!err, 'saved a doc with post');
      start();
    });
  });
});
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

'use strict';

var fs = require('fs');
var path = require('path');

var _ = require('underscore');
var async = require('async');
var pbjs = require('protobufjs/cli/pbjs');
var parseArgs = require('minimist');
var Mustache = require('mustache');

var package_json = require('../package.json');

var template_path = path.resolve(__dirname, 'service_packager');

var package_tpl_path = path.join(template_path, 'package.json.template');

var arg_format = {
  string: ['include', 'out', 'name', 'version'],
  alias: {
    include: 'i',
    out: 'o',
    name: 'n',
    version: 'v'
  }
};

// TODO(mlumish): autogenerate README.md from proto file

function generatePackage(params, callback) {
  fs.readFile(package_tpl_path, {encoding: 'utf-8'}, function(err, template) {
    if (err) {
      callback(err);
    } else {
      var rendered = Mustache.render(template, params);
      callback(null, rendered);
    }
  });
}

function copyFile(src_path, dest_path) {
  fs.createReadStream(src_path).pipe(fs.createWriteStream(dest_path));
}

function main(argv) {
  var args = parseArgs(argv, arg_format);
  var out_path = path.resolve(args.out);
  var include_dirs = _.map(_.flatten([args.include]), function(p) {
    return path.resolve(p);
  });
  args.grpc_version = package_json.version;
  generatePackage(args, function(err, rendered) {
    if (err) throw err;
    fs.writeFile(path.join(out_path, 'package.json'), rendered, function(err) {
      if (err) throw err;
    });
  });
  copyFile(path.join(template_path, 'index.js'),
           path.join(out_path, 'index.js'));
  copyFile(path.join(__dirname, '..', 'LICENSE'),
           path.join(out_path, 'LICENSE'));

  var service_stream = fs.createWriteStream(path.join(out_path,
                                                      'service.json'));
  var pbjs_args = _.flatten(['node', 'pbjs',
                             args._[0],
                             '-legacy',
                             _.map(include_dirs, function(dir) {
                               return "-path=" + dir;
                             })]);
  var old_stdout = process.stdout;
  process.__defineGetter__('stdout', function() {
    return service_stream;
  });
  var pbjs_status = pbjs.main(pbjs_args);
  process.__defineGetter__('stdout', function() {
    return old_stdout;
  });
  if (pbjs_status !== pbjs.STATUS_OK) {
    throw new Error('pbjs failed with status code ' + pbjs_status);
  }
}

exports.main = main;
<commit_msg>Fixed include path handling<commit_after>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

'use strict';

var fs = require('fs');
var path = require('path');

var _ = require('underscore');
var async = require('async');
var pbjs = require('protobufjs/cli/pbjs');
var parseArgs = require('minimist');
var Mustache = require('mustache');

var package_json = require('../package.json');

var template_path = path.resolve(__dirname, 'service_packager');

var package_tpl_path = path.join(template_path, 'package.json.template');

var arg_format = {
  string: ['include', 'out', 'name', 'version'],
  alias: {
    include: 'i',
    out: 'o',
    name: 'n',
    version: 'v'
  }
};

// TODO(mlumish): autogenerate README.md from proto file

function generatePackage(params, callback) {
  fs.readFile(package_tpl_path, {encoding: 'utf-8'}, function(err, template) {
    if (err) {
      callback(err);
    } else {
      var rendered = Mustache.render(template, params);
      callback(null, rendered);
    }
  });
}

function copyFile(src_path, dest_path) {
  fs.createReadStream(src_path).pipe(fs.createWriteStream(dest_path));
}

function main(argv) {
  var args = parseArgs(argv, arg_format);
  var out_path = path.resolve(args.out);
  var include_dirs = [];
  if (args.include) {
    include_dirs = _.map(_.flatten([args.include]), function(p) {
      return path.resolve(p);
    });
  }
  args.grpc_version = package_json.version;
  generatePackage(args, function(err, rendered) {
    if (err) throw err;
    fs.writeFile(path.join(out_path, 'package.json'), rendered, function(err) {
      if (err) throw err;
    });
  });
  copyFile(path.join(template_path, 'index.js'),
           path.join(out_path, 'index.js'));
  copyFile(path.join(__dirname, '..', 'LICENSE'),
           path.join(out_path, 'LICENSE'));

  var service_stream = fs.createWriteStream(path.join(out_path,
                                                      'service.json'));
  var pbjs_args = _.flatten(['node', 'pbjs',
                             args._[0],
                             '-legacy',
                             _.map(include_dirs, function(dir) {
                               return "-path=" + dir;
                             })]);
  var old_stdout = process.stdout;
  process.__defineGetter__('stdout', function() {
    return service_stream;
  });
  var pbjs_status = pbjs.main(pbjs_args);
  process.__defineGetter__('stdout', function() {
    return old_stdout;
  });
  if (pbjs_status !== pbjs.STATUS_OK) {
    throw new Error('pbjs failed with status code ' + pbjs_status);
  }
}

exports.main = main;
<|endoftext|>


<commit_before>var sakai = sakai || {};
sakai.createsite = {};

(function(){

	var newsitejson = false;
	var newpageid = false;
	var newsitetitle = false;

	$("#createsite_newsiteid_url").text(document.location.protocol + "//" + document.location.host + "/site/");
	$("#createsite_portfolio_newsiteid_url").text(document.location.protocol + "//" + document.location.host + "/site/");

	sakai.createsite.initialise = function(){
		$("#create-site-course").hide();
		$("#create-site-noncourse").show();
		$("#create-site-course-requested").hide();
		$("#create-site-communal-1").show();
		$("#create-site-communal-2").show();
		$("#createsite_step2").show();
		$("#createsite_overlay-lightbox").show();
	}

	$("#createsite_newsitename").bind("change", function(ev){
		var entered = $("#createsite_newsitename").val().toLowerCase().replace(/ /g,"-");
		$("#createsite_newsiteid").val(entered);
	});

	sakai.createsite.navigate = function(source,destination){
		$("#" + source).hide();
		$("#" + destination).show();

	}

	sakai.createsite.doStep2 = function(){
		$("#createsite_step1").hide();
		$("#createsite_step2").show();
	}
	sakai.createsite.closeWindow = function(){
		$("#createsite_step1").hide();
		$("#createsite_overlay-lightbox").hide();
	}

	// add onclick to close window
    $('a.sakai-create-site-close-window').click(function(){
		$(".overlay-lightbox2").hide();
		$("#createsite_overlay-lightbox").hide();
    });

	$("#createsite_course_option").bind("click", function(ev){
		$("#create-site-noncourse").hide();
		$("#create-site-course").show();
	});
	$("#createsite_noncourse_option").bind("click", function(ev){
		$("#create-site-course").hide();
		$("#create-site-noncourse").show();
	});
	sakai.createsite.requestSite = function(){
		$("#create-site-course").hide();
		$("#create-site-communal-1").hide();
		$("#create-site-communal-2").hide();
		$("#create-site-course-requested").show();
	};

	sakai.createsite.createSite = function(){

		var sitetitle = $("#createsite_newsitename").val();
		var sitedescription = $("#createsite_newsitedescription").val() || "";
		var siteid = $("#createsite_newsiteid").val();

		var url = "/rest/site";

		if (!siteid)
		{
			alert("Please specify a site URL. ");
			return;
		}

		//id, name, description, type
		var parameters = {"name" : sitetitle, "description" : sitedescription, "id" : siteid, "type" : "project" };

		sdata.Ajax.request({
			url :"/rest/site/" + "checkId?id=" + siteid + "&sid=" + Math.random(),
			httpMethod : "GET",
			onSuccess : function(data) {
				alert("A site with this URL already exists");
			},
			onFail : function(status) {
				if (status != 403) {
					sdata.Ajax.request({
						url: "/rest/site/create",
						httpMethod: "POST",
						onSuccess: function(data){
							document.location = "/dev/site.html?siteid=" + siteid;
						},
						onFail: function(status){
							if (status == 409 || status == "409") {
								alert("A site with this URL already exists");
							}
							else {
								alert("An error has occured whilst creating the site");
							}
						},
						postData: parameters,
						contentType: "application/x-www-form-urlencoded"
					});
				} else {
					alert("A site with this URL already exists");
				}
			},
		});
	}

	sakai.createsite.createPortfolio = function(){
		// title is a required field
		var sitetitle = $("#createsite_portfolio_newsitename").attr("value");
		if (!sitetitle)
		{
			alert("Please specify site title. ");
			return;
		}

		var siteid = $("#createsite_portfolio_newsiteid").attr("value");
		if (!siteid)
		{
			alert("Please specify a site URL. ");
			return;
		}

		var sitedescription = null;
		if (!sitedescription)
		{
			sitedescription ="";
		}

		var skin = null;
		var skinselector = document.getElementById("createsite_portfolio_skin");
		skin = skinselector.options[skinselector.selectedIndex].value;

		if (sitetitle && siteid)
		{

			sdata.Ajax.request({
				url :"/direct/site/" + siteid + "/exists",
				httpMethod : "GET",
				onSuccess : function(data) {
					alert("This site url already exists");
				},
				onFail : function(status) {
					newsitetitle = sitetitle;

					var url = "/sdata/newsite";
					var parameters = {"sitename" : sitetitle, "sitedescription" : sitedescription, "siteid" : siteid, "template" : "template001", "skin": skin, "type" : "portfolio" };

					sdata.Ajax.request({
						url :url,
						httpMethod : "POST",
						onSuccess : function(data) {
							document.location = "/site/" + siteid;
						},
						onFail : function(status) {
							alert("An error occured");
						},
						postData : parameters,
						contentType : "application/x-www-form-urlencoded"
					});
				}
			});

		}
	}

	randomString = function(string_length) {
		var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
		var randomstring = '';
		for (var i=0; i<string_length; i++) {
			var rnum = Math.floor(Math.random() * chars.length);
			randomstring += chars.substring(rnum,rnum+1);
		}
		return randomstring;
	}

	createPage1 = function(response, exists){
		if (exists){
			newsitejson = eval('(' + response + ')');
			if (newsitejson.status == "success") {
				newpageid = randomString(8);
				newpageid = newpageid.replace(/\//g, "_");
				newpageid = newpageid.replace(/"/g, "_");
				newpageid = newpageid.replace(/'/g, "_");
				sdata.widgets.WidgetPreference.save("/sdata/f/" + newsitejson.id + "/pages/" + newpageid, "metadata", '{"type":"webpage"}', createPage2);
			} else {
				alert("An error has occured");
			}
		} else {
			alert("An error has occured");
		}
	}

	createPage2 = function(success){
		if (success){
			sdata.Ajax.request({
				url :"/sdata/f/" + newsitejson.id + "/pageconfiguration?sid=" + Math.random(),
				httpMethod : "GET",
				onSuccess : function(data) {
					createPage3(data,true);
				},
				onFail : function(status) {
					createPage3(status,false);
				}
			});
		} else {
			alert("An error has occured");
		}
	}

	createPage3 = function(response, exists){
		var pagetitle = "Welcome";
		var json = {};
		json.items = [];
		if (exists){
			json = eval('(' + response + ')');
		}
		var index = json.items.length;
		json.items[index] = {};
		json.items[index].id = newpageid;
		json.items[index].title = "Welcome";
		json.items[index].type = "webpage";
		json.items[index].top = true;
		var tostring = sdata.JSON.stringify(json);
		sdata.widgets.WidgetPreference.save("/sdata/f/" + newsitejson.id + "", "pageconfiguration", tostring, createPage4);
	}

	createPage4 = function(success){
		sdata.widgets.WidgetPreference.save("/sdata/f/" + newsitejson.id + "/pages/" + newpageid, "content", "Welcome to " + newsitetitle + " !", doRedirect);
	}

	doRedirect = function(success){
		if (success){
			document.location = "/dev/site_home_page.html?siteid=" + newsitejson.id;
		} else {
			alert("An error occured");
		}
	}

})();<commit_msg>SAK-15672<commit_after>var sakai = sakai || {};
sakai.createsite = {};

(function(){

	var newsitejson = false;
	var newpageid = false;
	var newsitetitle = false;

	$("#createsite_newsiteid_url").text(document.location.protocol + "//" + document.location.host + "/site/");
	$("#createsite_portfolio_newsiteid_url").text(document.location.protocol + "//" + document.location.host + "/site/");

	sakai.createsite.initialise = function(){
		$("#create-site-course").hide();
		$("#create-site-noncourse").show();
		$("#create-site-course-requested").hide();
		$("#create-site-communal-1").show();
		$("#create-site-communal-2").show();
		$("#createsite_step2").show();
		$("#createsite_overlay-lightbox").show();
	}

	$("#createsite_newsitename").bind("change", function(ev){
		var entered = $("#createsite_newsitename").val().toLowerCase().replace(/ /g,"-");
		entered = entered.replace(/[:]/g,"_");
		entered = entered.replace(/[?]/g,"_");
		entered = entered.replace(/[=]/g,"_");
		$("#createsite_newsiteid").val(entered);
	});

	sakai.createsite.navigate = function(source,destination){
		$("#" + source).hide();
		$("#" + destination).show();

	}

	sakai.createsite.doStep2 = function(){
		$("#createsite_step1").hide();
		$("#createsite_step2").show();
	}
	sakai.createsite.closeWindow = function(){
		$("#createsite_step1").hide();
		$("#createsite_overlay-lightbox").hide();
	}

	// add onclick to close window
    $('a.sakai-create-site-close-window').click(function(){
		$(".overlay-lightbox2").hide();
		$("#createsite_overlay-lightbox").hide();
    });

	$("#createsite_course_option").bind("click", function(ev){
		$("#create-site-noncourse").hide();
		$("#create-site-course").show();
	});
	$("#createsite_noncourse_option").bind("click", function(ev){
		$("#create-site-course").hide();
		$("#create-site-noncourse").show();
	});
	sakai.createsite.requestSite = function(){
		$("#create-site-course").hide();
		$("#create-site-communal-1").hide();
		$("#create-site-communal-2").hide();
		$("#create-site-course-requested").show();
	};

	sakai.createsite.createSite = function(){

		var sitetitle = $("#createsite_newsitename").val();
		var sitedescription = $("#createsite_newsitedescription").val() || "";
		var siteid = $("#createsite_newsiteid").val();

		siteid = siteid.replace(/[:]/g,"_");
		siteid = siteid.replace(/[?]/g,"_");
		siteid = siteid.replace(/[=]/g,"_");

		var url = "/rest/site";

		if (!siteid)
		{
			alert("Please specify a site URL. ");
			return;
		}

		//id, name, description, type
		var parameters = {"name" : sitetitle, "description" : sitedescription, "id" : siteid, "type" : "project" };

		sdata.Ajax.request({
			url :"/rest/site/" + "checkId?id=" + siteid + "&sid=" + Math.random(),
			httpMethod : "GET",
			onSuccess : function(data) {
				alert("A site with this URL already exists");
			},
			onFail : function(status) {
				if (status != 403) {
					sdata.Ajax.request({
						url: "/rest/site/create",
						httpMethod: "POST",
						onSuccess: function(data){
							document.location = "/dev/site.html?siteid=" + siteid;
						},
						onFail: function(status){
							if (status == 409 || status == "409") {
								alert("A site with this URL already exists");
							}
							else {
								alert("An error has occured whilst creating the site");
							}
						},
						postData: parameters,
						contentType: "application/x-www-form-urlencoded"
					});
				} else {
					alert("A site with this URL already exists");
				}
			},
		});
	}

	sakai.createsite.createPortfolio = function(){
		// title is a required field
		var sitetitle = $("#createsite_portfolio_newsitename").attr("value");
		if (!sitetitle)
		{
			alert("Please specify site title. ");
			return;
		}

		var siteid = $("#createsite_portfolio_newsiteid").attr("value");
		if (!siteid)
		{
			alert("Please specify a site URL. ");
			return;
		}

		var sitedescription = null;
		if (!sitedescription)
		{
			sitedescription ="";
		}

		var skin = null;
		var skinselector = document.getElementById("createsite_portfolio_skin");
		skin = skinselector.options[skinselector.selectedIndex].value;

		if (sitetitle && siteid)
		{

			sdata.Ajax.request({
				url :"/direct/site/" + siteid + "/exists",
				httpMethod : "GET",
				onSuccess : function(data) {
					alert("This site url already exists");
				},
				onFail : function(status) {
					newsitetitle = sitetitle;

					var url = "/sdata/newsite";
					var parameters = {"sitename" : sitetitle, "sitedescription" : sitedescription, "siteid" : siteid, "template" : "template001", "skin": skin, "type" : "portfolio" };

					sdata.Ajax.request({
						url :url,
						httpMethod : "POST",
						onSuccess : function(data) {
							document.location = "/site/" + siteid;
						},
						onFail : function(status) {
							alert("An error occured");
						},
						postData : parameters,
						contentType : "application/x-www-form-urlencoded"
					});
				}
			});

		}
	}

	randomString = function(string_length) {
		var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
		var randomstring = '';
		for (var i=0; i<string_length; i++) {
			var rnum = Math.floor(Math.random() * chars.length);
			randomstring += chars.substring(rnum,rnum+1);
		}
		return randomstring;
	}

	createPage1 = function(response, exists){
		if (exists){
			newsitejson = eval('(' + response + ')');
			if (newsitejson.status == "success") {
				newpageid = randomString(8);
				newpageid = newpageid.replace(/\//g, "_");
				newpageid = newpageid.replace(/"/g, "_");
				newpageid = newpageid.replace(/'/g, "_");
				sdata.widgets.WidgetPreference.save("/sdata/f/" + newsitejson.id + "/pages/" + newpageid, "metadata", '{"type":"webpage"}', createPage2);
			} else {
				alert("An error has occured");
			}
		} else {
			alert("An error has occured");
		}
	}

	createPage2 = function(success){
		if (success){
			sdata.Ajax.request({
				url :"/sdata/f/" + newsitejson.id + "/pageconfiguration?sid=" + Math.random(),
				httpMethod : "GET",
				onSuccess : function(data) {
					createPage3(data,true);
				},
				onFail : function(status) {
					createPage3(status,false);
				}
			});
		} else {
			alert("An error has occured");
		}
	}

	createPage3 = function(response, exists){
		var pagetitle = "Welcome";
		var json = {};
		json.items = [];
		if (exists){
			json = eval('(' + response + ')');
		}
		var index = json.items.length;
		json.items[index] = {};
		json.items[index].id = newpageid;
		json.items[index].title = "Welcome";
		json.items[index].type = "webpage";
		json.items[index].top = true;
		var tostring = sdata.JSON.stringify(json);
		sdata.widgets.WidgetPreference.save("/sdata/f/" + newsitejson.id + "", "pageconfiguration", tostring, createPage4);
	}

	createPage4 = function(success){
		sdata.widgets.WidgetPreference.save("/sdata/f/" + newsitejson.id + "/pages/" + newpageid, "content", "Welcome to " + newsitetitle + " !", doRedirect);
	}

	doRedirect = function(success){
		if (success){
			document.location = "/dev/site_home_page.html?siteid=" + newsitejson.id;
		} else {
			alert("An error occured");
		}
	}

})();<|endoftext|>