<commit_before>/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

/*
 * Dependencies
 *
 * /dev/lib/jquery/plugins/jqmodal.sakai-edited.js
 * /dev/lib/misc/trimpath.template.js (TrimpathTemplates)
 * /dev/lib/jquery/plugins/jquery.threedots.js (ThreeDots)
 */

/*global $ */
require(["jquery", "sakai/sakai.api.core", "/dev/javascript/content_profile.js"], function($, sakai) {

    /**
     * @name sakai_global.contentmetadata
     *
     * @class contentmetadata
     *
     * @description
     * Initialize the contentmetadata widget
     *
     * @version 0.0.1
     * @param {String} tuid Unique id of the widget
     * @param {Boolean} showSettings Show the settings of the widget or not
     */
    sakai_global.contentmetadata = function(tuid,showSettings){

        ////////////////////////
        ////// VARIABLES ///////
        ////////////////////////

        // Containers
        var $contentmetadataDescriptionContainer = $("#contentmetadata_description_container");
        var $contentmetadataTagsContainer = $("#contentmetadata_tags_container");
        var $contentmetadataCopyrightContainer = $("#contentmetadata_copyright_container");
        var $contentmetadataDetailsContainer = $("#contentmetadata_details_container");
        var $contentmetadataLocationsContainer = $("#contentmetadata_locations_container");
        var $contentmetadataLocationsDialogContainer = $("#contentmetadata_locations_dialog_container");
        var contentmetadataLocationsNewLocationsContainer = "#contentmetadata_locations_newlocations_container";
        var contentmetadataLocationsSecondLevelTemplateContainer = "#contentmetadata_location_secondlevel_template_container";
        var contentmetadataLocationsThirdLevelTemplateContainer = "#contentmetadata_location_thirdlevel_template_container";

        // Dialogs
        //var $contentmetadataLocationsDialog = $("#contentmetadata_locations_dialog");

        // Elements
        var contentmetadataDescriptionDisplay = "#contentmetadata_description_display";
        var $collapsibleContainers = $(".collapsible_container");
        var contentmetadataViewRevisions = "#contentmetadata_view_revisions";
        var $contentmetadataEditable = $(".contentmetadata_editable");
        var contentmetadataCancelSave = ".contentmetadata_cancel_save";
        var contentmetadataSave = ".contentmetadata_save";
        var contentmetadataInputEdit = ".contentmetadata_edit_input";
        var $contentmetadataLocationsAddAnother = $("#contentmetadata_locations_add_another");
        var contentmetadataLocationLvlOne = ".contentmetadata_location_directory_lvlone";
        var contentmetadataLocationLvlTwo = ".contentmetadata_location_directory_lvltwo";
        var contentmetadataLocationLvlThree = ".contentmetadata_location_directory_lvlthree";
        var $contentmetadataLocationsDialogUpdate = $("#contentmetadata_locations_dialog_update");
        var contentmetadataRemoveLocation = ".contentmetadata_remove_location";
        var contentmetadataRemoveNewLocation = ".contentmetadata_remove_new_location";

        // See more
        var $contentmetadataShowMore = $("#contentmetadata_show_more");
        var $contentmetadataSeeMore = $("#contentmetadata_see_more");
        var $contentmetadataSeeLess = $("#contentmetadata_see_less");

        // Templates
        var contentmetadataDescriptionTemplate = "contentmetadata_description_template";
        var contentmetadataTagsTemplate = "contentmetadata_tags_template";
        var contentmetadataCopyrightTemplate = "contentmetadata_copyright_template";
        var contentmetadataDetailsTemplate = "contentmetadata_details_template";
        var contentmetadataLocationsTemplate = "contentmetadata_locations_template";
        var contentmetadataLocationsDialogTemplate = "contentmetadata_locations_dialog_template";
        var contentmetadataLocationFirstLevelTemplate= "contentmetadata_location_firstlevel_template";
        var contentmetadataLocationSecondLevelTemplate= "contentmetadata_location_secondlevel_template";
        var contentmetadataLocationThirdLevelTemplate= "contentmetadata_location_thirdlevel_template";

        // i18n
        var $contentmetadataUpdatedCopyright = $("#contentmetadata_updated_copyright");

        // Edit vars
        // Parent DIV that handles the hover and click to edit
        var editTarget = "";
        // ID of Input element that's focused, defines what to update
        var edittingElement = "";
        var directoryJSON = {};

        ////////////////////////
        ////// RENDERING ///////
        ////////////////////////

        /**
         * Add binding to the input elements that allow editting
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var addEditBinding = function(mode){
            if (mode === "edit") {
                if ($(".contentmetadata_edit_input")[0] !== undefined) {
                    $(".contentmetadata_edit_input")[0].focus();
                }

                $(contentmetadataInputEdit).blur(editInputBlur);
            }
        };

        /**
         * Render the Description template
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var renderDescription = function(mode){
            sakai_global.content_profile.content_data.mode = mode;
            var json = {
                data: sakai_global.content_profile.content_data,
                sakai: sakai
            };
            $contentmetadataDescriptionContainer.html(sakai.api.Util.TemplateRenderer(contentmetadataDescriptionTemplate, json));
            addEditBinding(mode);
        };

        var renderName = function(mode){
            if (mode === "edit"){
                $("#contentmetadata_name_name").hide();
                $("#contentmetadata_name_text").val($.trim($("#contentmetadata_name_name").text()));
                $("#contentmetadata_name_edit").show();
                $("#contentmetadata_name_text").focus();
            }
            $("#contentmetadata_name_text").unbind("blur");
            $("#contentmetadata_name_text").bind("blur", function(){
                $("#contentmetadata_name_edit").hide();
                if ($.trim($("#contentmetadata_name_text").val())) {
                    $("#contentmetadata_name_name").text($("#contentmetadata_name_text").val());
                    $("#contentmetadata_name_name").show();
                    $.ajax({
                        url: "/p/" + sakai_global.content_profile.content_data.data["jcr:name"] + ".html",
                        type : "POST",
                        cache: false,
                        data: {
                            "sakai:pooled-content-file-name":sakai.api.Security.escapeHTML($("#contentmetadata_name_text").val())
                        },
                        success: function() {
                            sakai_global.content_profile.content_data.data["sakai:pooled-content-file-name"] = sakai.api.Security.escapeHTML($("#contentmetadata_name_text").val());
                        }
                    });
                } else {
                    $("#contentmetadata_name_name").show();
                    $(".contentmetadata_editable").live("click", editData);
                }
            });
        };

        /**
         * Render the Tags template
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var renderTags = function(mode){
            sakai_global.content_profile.content_data.mode = mode;
            var json = {
                data: sakai_global.content_profile.content_data,
                sakai: sakai
            };
            $contentmetadataTagsContainer.html(sakai.api.Util.TemplateRenderer(contentmetadataTagsTemplate, json));
            addEditBinding(mode);
        };

        /**
         * Render the Copyright template
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var renderCopyright = function(mode){
            sakai_global.content_profile.content_data.mode = mode;
            var json = {
                data: sakai_global.content_profile.content_data,
                sakai: sakai
            };
            $contentmetadataCopyrightContainer.html(sakai.api.Util.TemplateRenderer(contentmetadataCopyrightTemplate, json));
            addEditBinding(mode);
        };

        /**
         * Render the Details template
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var renderDetails = function(mode){
            sakai_global.content_profile.content_data.mode = mode;
            var json = {
                data: sakai_global.content_profile.content_data,
                sakai: sakai
            };
            $contentmetadataDetailsContainer.html(sakai.api.Util.TemplateRenderer(contentmetadataDetailsTemplate, json));
            addEditBinding(mode);
        };

        var createActivity = function(activityMessage){
            var activityData = {
                "sakai:activityMessage": activityMessage
            };
            sakai.api.Activity.createActivity("/p/" + sakai_global.content_profile.content_data.data["jcr:name"], "content", "default", activityData);
        };

        //////////////////////////////////
        /////// DIRECTORY EDITTING ///////

        var renderLocationsEdit = function(){
            $("#assignlocation_container").jqmShow();
        };

        /**
         * Render the Locations template
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var renderLocations = function(mode){
            if (mode === "edit") {
                renderLocationsEdit();
            }
            else {
                $contentmetadataLocationsContainer.html("");
                sakai_global.content_profile.content_data.mode = mode;
                var json = {
                    data: sakai_global.content_profile.content_data,
                    sakai: sakai
                };
                $contentmetadataLocationsContainer.html(sakai.api.Util.TemplateRenderer(contentmetadataLocationsTemplate, json));
                applyThreeDots();
            }
        };

        ////////////////////////
        /////// EDITTING ///////
        ////////////////////////

        var updateTags = function() {
            var tags = sakai.api.Util.formatTags($("#contentmetadata_tags_tags").val());
            // Since directory tags are filtered out of the textarea we should put them back to save them
            $(sakai_global.content_profile.content_data.data["sakai:tags"]).each(function(index, tag){
                if(tag.split("/")[0] === "directory"){
                    tags.push(tag);
                }
            });

            sakai.api.Util.tagEntity("/p/" + sakai_global.content_profile.content_data.data["jcr:name"], tags, sakai_global.content_profile.content_data.data["sakai:tags"], function(){
                sakai_global.content_profile.content_data.data["sakai:tags"] = tags;
                renderTags(false);
                // Create an activity
                createActivity("__MSG__UPDATED_TAGS__");
            });
        };

        /**
         * Update the description of the content
         */
        var updateDescription = function(){
            var description = $("#contentmetadata_description_description").val();
            sakai_global.content_profile.content_data.data["sakai:description"] = description;
            renderDescription(false);
            $.ajax({
                url: "/p/" + sakai_global.content_profile.content_data.data["jcr:name"] + ".html",
                type : "POST",
                cache: false,
                data: {
                    "sakai:description": description
                }, success: function() {
                    createActivity("__MSG__UPDATED_DESCRIPTION__");
                }
            });
        };

        /**
         * Update the copyright of the content
         */
        var updateCopyright = function(){
            var copyright = $("#contentmetadata_copyright_copyright").val();
            sakai_global.content_profile.content_data.data["sakai:copyright"] = copyright;
            renderCopyright(false);
            $.ajax({
                url: "/p/" + sakai_global.content_profile.content_data.data["jcr:name"] + ".html",
                type : "POST",
                cache: false,
                data: {
                    "sakai:copyright":$("#contentmetadata_copyright_copyright").val()
                }, success: function() {
                    createActivity("__MSG__UPDATED_COPYRIGHT__");
                }
            });
        };

        /**
         * Trigger the template to render the edit mode
         * @param {Object} ev Trigger event
         */
        var editData = function(ev){
            var dataToEdit = "";
            if (ev.target.nodeName.toLowerCase() !== "a" && ev.target.nodeName.toLowerCase() !== "select" && ev.target.nodeName.toLowerCase() !== "option") {
                target = $(ev.target).closest(".contentmetadata_editable");
                if (target[0] !== undefined) {
                    editTarget = target;
                    dataToEdit = editTarget[0].id.split("_")[1];

                    switch (dataToEdit){
                        case "description":
                            renderDescription("edit");
                            break;
                        case "tags":
                            renderTags("edit");
                            break;
                        case "locations":
                            renderLocations("edit");
                            break;
                        case "copyright":
                            renderCopyright("edit");
                            break;
                        case "name":
                            renderName("edit");
                            break;
                    }
                }
            }
        };

        /**
         * Handle losing of focus on an input element
         * @param {Object} el Element that lost the focus
         */
        var editInputBlur = function(el){
            edittingElement = $(el.target)[0].id.split("_")[2];
            switch (edittingElement){
                case "description":
                    updateDescription();
                    break;
                case "tags":
                    updateTags();
                    break;
                case "copyright":
                    updateCopyright();
                    break;
            }
        };

        ////////////////////////
        //////// SET-UP ////////
        ////////////////////////

        var applyThreeDots = function(){
            // make sure the newly added content is properly styled with
            // threedots truncation
            $(".threedots_text").ThreeDots({
                max_rows: 1,
                text_span_class: "ellipsis_text",
                e_span_class: "threedots_a",
                whole_word: false,
                alt_text_t: true
            });
        };

        /**
         * Animate the hidden or shown data containers
         */
        var animateData = function(){
            $collapsibleContainers.animate({
                'margin-bottom': 'toggle',
                opacity: 'toggle',
                'padding-top': 'toggle',
                'padding-bottom': 'toggle',
                height: 'toggle'
            }, 400, function(){
                applyThreeDots();
            });
            $("#contentmetadata_show_more > span").toggle();
        };

        /**
         * Add binding/events to the elements in the widget
         */
        var addBinding = function(){
            $(".contentmetadata_editable_for_maintainers").removeClass("contentmetadata_editable");
            if (sakai_global.content_profile.content_data.isManager) {
                $(".contentmetadata_editable_for_maintainers").addClass("contentmetadata_editable");
            }

            $contentmetadataShowMore.unbind("click", animateData);
            $contentmetadataShowMore.bind("click", animateData);

            $(".contentmetadata_editable").die("click", editData);
            $(".contentmetadata_editable").live("click", editData);

            $(contentmetadataViewRevisions).die("click");
            $(contentmetadataViewRevisions).live("click", function(){
                $(window).trigger("initialize.filerevisions.sakai", sakai_global.content_profile.content_data);
            });
        };

        /**
         * Initialize the widget
         */
        var doInit = function(){
            // Render all information
            renderDescription(false);
            renderTags(false);
            renderCopyright(false);
            renderLocations(false);
            renderDetails(false);

            // Add binding
            addBinding();
        };

        $(window).bind("sakai-fileupload-complete", function(){
            sakai_global.content_profile.loadContentProfile(renderDetails);
        });

        $(window).bind("sakai-contentmetadata-renderlocations", function(ev, val){
            sakai_global.content_profile.content_data.saveddirectory = val.saveddirectory;
            sakai_global.content_profile.content_data.data["sakai:tags"] = val.tags;
            renderLocations(false);
        });

        // Bind Enter key to input fields to save on keyup
        $("input").bind("keyup", function(ev){
            if(ev.keyCode == 13){
                $(this).blur();
            }
        });

        /**
         * Initialize the widget from outside of the widget
         */
        $(window).bind("render.contentmetadata.sakai", function(){
            doInit();
        });
        sakai_global.contentmetadata.isReady = true;
        $(window).trigger("sakai.contentmetadata.ready");
    };

    sakai.api.Widgets.widgetLoader.informOnLoad("contentmetadata");
});
<commit_msg>SAKIII-2303 Fix issue where users could not click into the textarea and move their cursor to another position<commit_after>/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

/*
 * Dependencies
 *
 * /dev/lib/jquery/plugins/jqmodal.sakai-edited.js
 * /dev/lib/misc/trimpath.template.js (TrimpathTemplates)
 * /dev/lib/jquery/plugins/jquery.threedots.js (ThreeDots)
 */

/*global $ */
require(["jquery", "sakai/sakai.api.core", "/dev/javascript/content_profile.js"], function($, sakai) {

    /**
     * @name sakai_global.contentmetadata
     *
     * @class contentmetadata
     *
     * @description
     * Initialize the contentmetadata widget
     *
     * @version 0.0.1
     * @param {String} tuid Unique id of the widget
     * @param {Boolean} showSettings Show the settings of the widget or not
     */
    sakai_global.contentmetadata = function(tuid,showSettings){

        ////////////////////////
        ////// VARIABLES ///////
        ////////////////////////

        // Containers
        var $contentmetadataDescriptionContainer = $("#contentmetadata_description_container");
        var $contentmetadataTagsContainer = $("#contentmetadata_tags_container");
        var $contentmetadataCopyrightContainer = $("#contentmetadata_copyright_container");
        var $contentmetadataDetailsContainer = $("#contentmetadata_details_container");
        var $contentmetadataLocationsContainer = $("#contentmetadata_locations_container");
        var $contentmetadataLocationsDialogContainer = $("#contentmetadata_locations_dialog_container");
        var contentmetadataLocationsNewLocationsContainer = "#contentmetadata_locations_newlocations_container";
        var contentmetadataLocationsSecondLevelTemplateContainer = "#contentmetadata_location_secondlevel_template_container";
        var contentmetadataLocationsThirdLevelTemplateContainer = "#contentmetadata_location_thirdlevel_template_container";

        // Dialogs
        //var $contentmetadataLocationsDialog = $("#contentmetadata_locations_dialog");

        // Elements
        var contentmetadataDescriptionDisplay = "#contentmetadata_description_display";
        var $collapsibleContainers = $(".collapsible_container");
        var contentmetadataViewRevisions = "#contentmetadata_view_revisions";
        var $contentmetadataEditable = $(".contentmetadata_editable");
        var contentmetadataCancelSave = ".contentmetadata_cancel_save";
        var contentmetadataSave = ".contentmetadata_save";
        var contentmetadataInputEdit = ".contentmetadata_edit_input";
        var $contentmetadataLocationsAddAnother = $("#contentmetadata_locations_add_another");
        var contentmetadataLocationLvlOne = ".contentmetadata_location_directory_lvlone";
        var contentmetadataLocationLvlTwo = ".contentmetadata_location_directory_lvltwo";
        var contentmetadataLocationLvlThree = ".contentmetadata_location_directory_lvlthree";
        var $contentmetadataLocationsDialogUpdate = $("#contentmetadata_locations_dialog_update");
        var contentmetadataRemoveLocation = ".contentmetadata_remove_location";
        var contentmetadataRemoveNewLocation = ".contentmetadata_remove_new_location";

        // See more
        var $contentmetadataShowMore = $("#contentmetadata_show_more");
        var $contentmetadataSeeMore = $("#contentmetadata_see_more");
        var $contentmetadataSeeLess = $("#contentmetadata_see_less");

        // Templates
        var contentmetadataDescriptionTemplate = "contentmetadata_description_template";
        var contentmetadataTagsTemplate = "contentmetadata_tags_template";
        var contentmetadataCopyrightTemplate = "contentmetadata_copyright_template";
        var contentmetadataDetailsTemplate = "contentmetadata_details_template";
        var contentmetadataLocationsTemplate = "contentmetadata_locations_template";
        var contentmetadataLocationsDialogTemplate = "contentmetadata_locations_dialog_template";
        var contentmetadataLocationFirstLevelTemplate= "contentmetadata_location_firstlevel_template";
        var contentmetadataLocationSecondLevelTemplate= "contentmetadata_location_secondlevel_template";
        var contentmetadataLocationThirdLevelTemplate= "contentmetadata_location_thirdlevel_template";

        // i18n
        var $contentmetadataUpdatedCopyright = $("#contentmetadata_updated_copyright");

        // Edit vars
        // Parent DIV that handles the hover and click to edit
        var editTarget = "";
        // ID of Input element that's focused, defines what to update
        var edittingElement = "";
        var directoryJSON = {};

        ////////////////////////
        ////// RENDERING ///////
        ////////////////////////

        /**
         * Add binding to the input elements that allow editting
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var addEditBinding = function(mode){
            if (mode === "edit") {
                if ($(".contentmetadata_edit_input")[0] !== undefined) {
                    $(".contentmetadata_edit_input")[0].focus();
                }

                $(contentmetadataInputEdit).blur(editInputBlur);
            }
        };

        /**
         * Render the Description template
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var renderDescription = function(mode){
            sakai_global.content_profile.content_data.mode = mode;
            var json = {
                data: sakai_global.content_profile.content_data,
                sakai: sakai
            };
            $contentmetadataDescriptionContainer.html(sakai.api.Util.TemplateRenderer(contentmetadataDescriptionTemplate, json));
            addEditBinding(mode);
        };

        var renderName = function(mode){
            if (mode === "edit"){
                $("#contentmetadata_name_name").hide();
                $("#contentmetadata_name_text").val($.trim($("#contentmetadata_name_name").text()));
                $("#contentmetadata_name_edit").show();
                $("#contentmetadata_name_text").focus();
            }
            $("#contentmetadata_name_text").unbind("blur");
            $("#contentmetadata_name_text").bind("blur", function(){
                $("#contentmetadata_name_edit").hide();
                if ($.trim($("#contentmetadata_name_text").val())) {
                    $("#contentmetadata_name_name").text($("#contentmetadata_name_text").val());
                    $("#contentmetadata_name_name").show();
                    $.ajax({
                        url: "/p/" + sakai_global.content_profile.content_data.data["jcr:name"] + ".html",
                        type : "POST",
                        cache: false,
                        data: {
                            "sakai:pooled-content-file-name":sakai.api.Security.escapeHTML($("#contentmetadata_name_text").val())
                        },
                        success: function() {
                            sakai_global.content_profile.content_data.data["sakai:pooled-content-file-name"] = sakai.api.Security.escapeHTML($("#contentmetadata_name_text").val());
                        }
                    });
                } else {
                    $("#contentmetadata_name_name").show();
                    $(".contentmetadata_editable").live("click", editData);
                }
            });
        };

        /**
         * Render the Tags template
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var renderTags = function(mode){
            sakai_global.content_profile.content_data.mode = mode;
            var json = {
                data: sakai_global.content_profile.content_data,
                sakai: sakai
            };
            $contentmetadataTagsContainer.html(sakai.api.Util.TemplateRenderer(contentmetadataTagsTemplate, json));
            addEditBinding(mode);
        };

        /**
         * Render the Copyright template
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var renderCopyright = function(mode){
            sakai_global.content_profile.content_data.mode = mode;
            var json = {
                data: sakai_global.content_profile.content_data,
                sakai: sakai
            };
            $contentmetadataCopyrightContainer.html(sakai.api.Util.TemplateRenderer(contentmetadataCopyrightTemplate, json));
            addEditBinding(mode);
        };

        /**
         * Render the Details template
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var renderDetails = function(mode){
            sakai_global.content_profile.content_data.mode = mode;
            var json = {
                data: sakai_global.content_profile.content_data,
                sakai: sakai
            };
            $contentmetadataDetailsContainer.html(sakai.api.Util.TemplateRenderer(contentmetadataDetailsTemplate, json));
            addEditBinding(mode);
        };

        var createActivity = function(activityMessage){
            var activityData = {
                "sakai:activityMessage": activityMessage
            };
            sakai.api.Activity.createActivity("/p/" + sakai_global.content_profile.content_data.data["jcr:name"], "content", "default", activityData);
        };

        //////////////////////////////////
        /////// DIRECTORY EDITTING ///////

        var renderLocationsEdit = function(){
            $("#assignlocation_container").jqmShow();
        };

        /**
         * Render the Locations template
         * @param {String|Boolean} mode Can be false or 'edit' depending on the mode you want to be in
         */
        var renderLocations = function(mode){
            if (mode === "edit") {
                renderLocationsEdit();
            }
            else {
                $contentmetadataLocationsContainer.html("");
                sakai_global.content_profile.content_data.mode = mode;
                var json = {
                    data: sakai_global.content_profile.content_data,
                    sakai: sakai
                };
                $contentmetadataLocationsContainer.html(sakai.api.Util.TemplateRenderer(contentmetadataLocationsTemplate, json));
                applyThreeDots();
            }
        };

        ////////////////////////
        /////// EDITTING ///////
        ////////////////////////

        var updateTags = function() {
            var tags = sakai.api.Util.formatTags($("#contentmetadata_tags_tags").val());
            // Since directory tags are filtered out of the textarea we should put them back to save them
            $(sakai_global.content_profile.content_data.data["sakai:tags"]).each(function(index, tag){
                if(tag.split("/")[0] === "directory"){
                    tags.push(tag);
                }
            });

            sakai.api.Util.tagEntity("/p/" + sakai_global.content_profile.content_data.data["jcr:name"], tags, sakai_global.content_profile.content_data.data["sakai:tags"], function(){
                sakai_global.content_profile.content_data.data["sakai:tags"] = tags;
                renderTags(false);
                // Create an activity
                createActivity("__MSG__UPDATED_TAGS__");
            });
        };

        /**
         * Update the description of the content
         */
        var updateDescription = function(){
            var description = $("#contentmetadata_description_description").val();
            sakai_global.content_profile.content_data.data["sakai:description"] = description;
            renderDescription(false);
            $.ajax({
                url: "/p/" + sakai_global.content_profile.content_data.data["jcr:name"] + ".html",
                type : "POST",
                cache: false,
                data: {
                    "sakai:description": description
                }, success: function() {
                    createActivity("__MSG__UPDATED_DESCRIPTION__");
                }
            });
        };

        /**
         * Update the copyright of the content
         */
        var updateCopyright = function(){
            var copyright = $("#contentmetadata_copyright_copyright").val();
            sakai_global.content_profile.content_data.data["sakai:copyright"] = copyright;
            renderCopyright(false);
            $.ajax({
                url: "/p/" + sakai_global.content_profile.content_data.data["jcr:name"] + ".html",
                type : "POST",
                cache: false,
                data: {
                    "sakai:copyright":$("#contentmetadata_copyright_copyright").val()
                }, success: function() {
                    createActivity("__MSG__UPDATED_COPYRIGHT__");
                }
            });
        };

        /**
         * Trigger the template to render the edit mode
         * @param {Object} ev Trigger event
         */
        var editData = function(ev){
            var dataToEdit = "";
            if (ev.target.nodeName.toLowerCase() !== "a" && ev.target.nodeName.toLowerCase() !== "select" && ev.target.nodeName.toLowerCase() !== "option" && ev.target.nodeName.toLowerCase() !== "textarea") {
                target = $(ev.target).closest(".contentmetadata_editable");
                if (target[0] !== undefined) {
                    editTarget = target;
                    dataToEdit = editTarget[0].id.split("_")[1];

                    switch (dataToEdit){
                        case "description":
                            renderDescription("edit");
                            break;
                        case "tags":
                            renderTags("edit");
                            break;
                        case "locations":
                            renderLocations("edit");
                            break;
                        case "copyright":
                            renderCopyright("edit");
                            break;
                        case "name":
                            renderName("edit");
                            break;
                    }
                }
            }
        };

        /**
         * Handle losing of focus on an input element
         * @param {Object} el Element that lost the focus
         */
        var editInputBlur = function(el){
            edittingElement = $(el.target)[0].id.split("_")[2];
            switch (edittingElement){
                case "description":
                    updateDescription();
                    break;
                case "tags":
                    updateTags();
                    break;
                case "copyright":
                    updateCopyright();
                    break;
            }
        };

        ////////////////////////
        //////// SET-UP ////////
        ////////////////////////

        var applyThreeDots = function(){
            // make sure the newly added content is properly styled with
            // threedots truncation
            $(".threedots_text").ThreeDots({
                max_rows: 1,
                text_span_class: "ellipsis_text",
                e_span_class: "threedots_a",
                whole_word: false,
                alt_text_t: true
            });
        };

        /**
         * Animate the hidden or shown data containers
         */
        var animateData = function(){
            $collapsibleContainers.animate({
                'margin-bottom': 'toggle',
                opacity: 'toggle',
                'padding-top': 'toggle',
                'padding-bottom': 'toggle',
                height: 'toggle'
            }, 400, function(){
                applyThreeDots();
            });
            $("#contentmetadata_show_more > span").toggle();
        };

        /**
         * Add binding/events to the elements in the widget
         */
        var addBinding = function(){
            $(".contentmetadata_editable_for_maintainers").removeClass("contentmetadata_editable");
            if (sakai_global.content_profile.content_data.isManager) {
                $(".contentmetadata_editable_for_maintainers").addClass("contentmetadata_editable");
            }

            $contentmetadataShowMore.unbind("click", animateData);
            $contentmetadataShowMore.bind("click", animateData);

            $(".contentmetadata_editable").die("click", editData);
            $(".contentmetadata_editable").live("click", editData);

            $(contentmetadataViewRevisions).die("click");
            $(contentmetadataViewRevisions).live("click", function(){
                $(window).trigger("initialize.filerevisions.sakai", sakai_global.content_profile.content_data);
            });
        };

        /**
         * Initialize the widget
         */
        var doInit = function(){
            // Render all information
            renderDescription(false);
            renderTags(false);
            renderCopyright(false);
            renderLocations(false);
            renderDetails(false);

            // Add binding
            addBinding();
        };

        $(window).bind("sakai-fileupload-complete", function(){
            sakai_global.content_profile.loadContentProfile(renderDetails);
        });

        $(window).bind("sakai-contentmetadata-renderlocations", function(ev, val){
            sakai_global.content_profile.content_data.saveddirectory = val.saveddirectory;
            sakai_global.content_profile.content_data.data["sakai:tags"] = val.tags;
            renderLocations(false);
        });

        // Bind Enter key to input fields to save on keyup
        $("input").bind("keyup", function(ev){
            if(ev.keyCode == 13){
                $(this).blur();
            }
        });

        /**
         * Initialize the widget from outside of the widget
         */
        $(window).bind("render.contentmetadata.sakai", function(){
            doInit();
        });
        sakai_global.contentmetadata.isReady = true;
        $(window).trigger("sakai.contentmetadata.ready");
    };

    sakai.api.Widgets.widgetLoader.informOnLoad("contentmetadata");
});
<|endoftext|>


<commit_before><commit_msg>new transcoder version<commit_after><|endoftext|>


<commit_before>/* -*- mode: espresso; espresso-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set softtabstop=2 shiftwidth=2 tabstop=2 expandtab: */

(function(CATMAID) {

  /**
   * Create a container to which one can push messages and coordinates. Both are
   * displayed separately from each other.
   */
  CATMAID.Console = function() {
    var view = document.createElement("div");
    view.className = "console";

    var coords = document.createElement("div");
    coords.id = "coordinates";
    coords.appendChild(document.createTextNode(""));
    view.appendChild(coords);
    view.appendChild(document.createElement("pre"));

    this.printCoords = function (obj) {
      coords.replaceChild(document.createTextNode(obj), coords.firstChild);
    };

    var toStr = function (obj, ins) {
      if (typeof ins == "undefined") ins = "";

      var type = typeof(obj);
      var str = "[" + type + "] ";

      switch (type) {
      case "function":
      case "object":
        if (ins.length <= 6) {
          str += "\r\n";
          for (var key in obj) {
            str += ins + "\"" + key + "\" => " + toStr(obj[key], ins + "  ") + "\r\n";
          }
        } else str += "...";
        break;
      case "undefined":
        break;
      default:
        str += obj;
        break;
      }
      return str;
    };

    this.setBottom = function() {
      view.style.bottom = "0px";
    };

    this.print = function (obj) {
      if (typeof obj == "string") view.lastChild.appendChild(document.createTextNode(obj));
      else
      view.lastChild.appendChild(document.createTextNode(toStr(obj)));
      return;
    };

    this.println = function (obj) {
      var sp = document.createElement("pre");
      if (typeof obj == "string") sp.appendChild(document.createTextNode(obj));
      else
      sp.appendChild(document.createTextNode(toStr(obj)));
      view.appendChild(sp);
      return;
    };

    this.replaceLast = function (obj) {
      var sp = document.createElement("pre");
      if (typeof obj == "string")
        sp.appendChild(document.createTextNode(obj));
      else
        sp.appendChild(document.createTextNode(toStr(obj)));
      view.replaceChild(sp, view.lastChild);
      return;
    };

    this.replaceLastHTML = function (html) {
      var e = document.createElement("pre");
      e.innerHTML = html;
      view.replaceChild(e, view.lastChild);
    };

    this.getView = function () {
      return view;
    };
  };

})(CATMAID);
<commit_msg>Console: don't create new nodes for every coordinate update<commit_after>/* -*- mode: espresso; espresso-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set softtabstop=2 shiftwidth=2 tabstop=2 expandtab: */

(function(CATMAID) {

  /**
   * Create a container to which one can push messages and coordinates. Both are
   * displayed separately from each other.
   */
  CATMAID.Console = function() {
    var view = document.createElement("div");
    view.className = "console";

    var coords = document.createElement("div");
    coords.id = "coordinates";
    var coordsText = document.createTextNode("");
    coords.appendChild(coordsText);
    view.appendChild(coords);
    view.appendChild(document.createElement("pre"));

    this.printCoords = function (obj) {
      coordsText.textContent = obj;
    };

    var toStr = function (obj, ins) {
      if (typeof ins == "undefined") ins = "";

      var type = typeof(obj);
      var str = "[" + type + "] ";

      switch (type) {
      case "function":
      case "object":
        if (ins.length <= 6) {
          str += "\r\n";
          for (var key in obj) {
            str += ins + "\"" + key + "\" => " + toStr(obj[key], ins + "  ") + "\r\n";
          }
        } else str += "...";
        break;
      case "undefined":
        break;
      default:
        str += obj;
        break;
      }
      return str;
    };

    this.setBottom = function() {
      view.style.bottom = "0px";
    };

    this.print = function (obj) {
      if (typeof obj == "string") view.lastChild.appendChild(document.createTextNode(obj));
      else
      view.lastChild.appendChild(document.createTextNode(toStr(obj)));
      return;
    };

    this.println = function (obj) {
      var sp = document.createElement("pre");
      if (typeof obj == "string") sp.appendChild(document.createTextNode(obj));
      else
      sp.appendChild(document.createTextNode(toStr(obj)));
      view.appendChild(sp);
      return;
    };

    this.replaceLast = function (obj) {
      var sp = document.createElement("pre");
      if (typeof obj == "string")
        sp.appendChild(document.createTextNode(obj));
      else
        sp.appendChild(document.createTextNode(toStr(obj)));
      view.replaceChild(sp, view.lastChild);
      return;
    };

    this.replaceLastHTML = function (html) {
      var e = document.createElement("pre");
      e.innerHTML = html;
      view.replaceChild(e, view.lastChild);
    };

    this.getView = function () {
      return view;
    };
  };

})(CATMAID);
<|endoftext|>


<commit_before>/*global define*/
define(['../Core/createGuid',
        '../Core/Cartographic',
        '../Core/DeveloperError',
        '../Core/Ellipsoid',
        '../Core/Event',
        '../Core/loadJson',
        './DynamicLabel',
        './DynamicObjectCollection',
        './StaticProperty',
        './StaticPositionProperty'
        ], function(
                createGuid,
                Cartographic,
                DeveloperError,
                Ellipsoid,
                Event,
                loadJson,
                DynamicLabel,
                DynamicObjectCollection,
                StaticProperty,
                StaticPositionProperty) {
    "use strict";

    function processFeature(feature, dynamicObjectCollection) {
        processors[feature.geometry.type](feature, dynamicObjectCollection);
    }

    function processFeatureCollection(featureCollection, dynamicObjectCollection) {
        var features = featureCollection.features;
        for ( var i = 0, len = features.length; i < len; i++) {
            var feature = features[i];
            processors[feature.type](feature, dynamicObjectCollection);
        }
    }

    function processGeometryCollection(geometryCollection, dynamicObjectCollection) {
        var geometries = geometryCollection.geometries;
        for ( var i = 0, len = geometries.length; i < len; i++) {
            var geometry = geometries[i];
            processors[geometry.type](geometry, dynamicObjectCollection);
        }
    }

    function processLineString(feature, dynamicObjectCollection) {
        var id = feature.id;
        if (typeof id === 'undefined') {
            id = createGuid();
        }
        var dynamicObject = dynamicObjectCollection.getOrCreateObject(id);
        dynamicObject.feature = feature;

        var coordinates = feature.geometry.coordinates;
        var positions = new Array(coordinates.length);
        for ( var i = 0; i < coordinates.length; i++) {
            positions[i] = Cartographic.fromDegrees(coordinates[i][0], coordinates[i][1]);
        }
        dynamicObject.vertexPositions = new StaticPositionProperty(Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions));
    }

    function processMultiLineString(feature, dynamicObjectCollection) {
        var lineStrings = feature.geometry.coordinates;
        for ( var i = 0; i < lineStrings.length; i++) {
            var lineString = lineStrings[i];
            var dynamicObject = dynamicObjectCollection.getOrCreateObject(createGuid());
            dynamicObject.feature = feature;

            for ( var q = 0; q < lineString.length; q++) {
                var positions = new Array(lineString.length);
                var index = 0;
                for ( var z = 0; z < lineString.length; z++) {
                    positions[index++] = Cartographic.fromDegrees(lineString[i][0], lineString[i][1]);
                }
                dynamicObject.vertexPositions = new StaticPositionProperty(Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions));
            }
        }
    }

    function processMultiPoint(feature, dynamicObjectCollection) {
        var coordinates = feature.geometry.coordinates;
        for ( var i = 0; i < coordinates.length; i++) {
            var dynamicObject = dynamicObjectCollection.getOrCreateObject(createGuid());
            dynamicObject.feature = feature;

            var position = Cartographic.fromDegrees(coordinates[i][0], coordinates[i][1]);
            dynamicObject.position = new StaticPositionProperty(Ellipsoid.WGS84.cartographicToCartesian(position));
        }
    }

    function processMultiPolygon(feature, dynamicObjectCollection) {
        var polygons = feature.geometry.coordinates;
        for ( var i = 0; i < polygons.length; i++) {
            var polygon = polygons[i];
            var dynamicObject = dynamicObjectCollection.getOrCreateObject(createGuid());
            dynamicObject.feature = feature;

            //TODO holes
            var vertexPositions = polygon[0];
            for ( var q = 0; q < vertexPositions.length; q++) {
                var positions = new Array(vertexPositions.length);
                var index = 0;
                for ( var z = 0; z < vertexPositions.length; z++) {
                    positions[index++] = Cartographic.fromDegrees(vertexPositions[i][0], vertexPositions[i][1]);
                }
                dynamicObject.vertexPositions = new StaticPositionProperty(Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions));
            }
        }
    }

    function processPoint(feature, dynamicObjectCollection) {
        var id = feature.id;
        if (typeof id === 'undefined') {
            id = createGuid();
        }
        var dynamicObject = dynamicObjectCollection.getOrCreateObject(id);
        dynamicObject.feature = feature;

        var coordinates = feature.geometry.coordinates;
        var position = Cartographic.fromDegrees(coordinates[0], coordinates[1]);
        dynamicObject.position = new StaticPositionProperty(Ellipsoid.WGS84.cartographicToCartesian(position));

        dynamicObject.label = new DynamicLabel();
        dynamicObject.label.text = new StaticProperty("This is GeoJSON!");
    }

    function processPolygon(feature, dynamicObjectCollection) {
        var id = feature.id;
        if (typeof id === 'undefined') {
            id = createGuid();
        }
        var dynamicObject = dynamicObjectCollection.getOrCreateObject(id);
        dynamicObject.feature = feature;

        //TODO Holes
        var coordinates = feature.geometry.coordinates[0];
        var positions = new Array(coordinates.length);
        var index = 0;
        for ( var i = 0; i < coordinates.length; i++) {
            positions[index++] = Cartographic.fromDegrees(coordinates[i][0], coordinates[i][1]);
        }
        dynamicObject.vertexPositions = new StaticPositionProperty(Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions));
    }

    var processors = {
        Feature : processFeature,
        FeatureCollection : processFeatureCollection,
        GeometryCollection : processGeometryCollection,
        LineString : processLineString,
        MultiLineString : processMultiLineString,
        MultiPoint : processMultiPoint,
        MultiPolygon : processMultiPolygon,
        Point : processPoint,
        Polygon : processPolygon
    };

    var GeoJsonDataSource = function() {
        this._changed = new Event();
        this._error = new Event();
        this._dynamicObjectCollection = new DynamicObjectCollection();
    };

    GeoJsonDataSource.prototype.getChangedEvent = function() {
        return this._changed;
    };

    GeoJsonDataSource.prototype.getErrorEvent = function() {
        return this._error;
    };

    GeoJsonDataSource.prototype.getClock = function() {
        return undefined;
    };

    GeoJsonDataSource.prototype.getDynamicObjectCollection = function() {
        return this._dynamicObjectCollection;
    };

    GeoJsonDataSource.prototype.getIsTimeVarying = function() {
        return false;
    };

    GeoJsonDataSource.prototype.load = function(geoJson) {
        if (typeof geoJson === 'undefined') {
            throw new DeveloperError('geoJson is required.');
        }

        this._dynamicObjectCollection.clear();

        if (typeof geoJson.type === 'undefined') {
            throw new DeveloperError('Invalid GeoJSON.  Type not defined');
        }

        var callback = processors[geoJson.type];
        if (typeof callback === 'undefined') {
            throw new DeveloperError('Unsupported feature type: ' + geoJson.type);
        }
        callback(geoJson, this._dynamicObjectCollection);
    };

    GeoJsonDataSource.prototype.loadUrl = function(url) {
        if (typeof url === 'undefined') {
            throw new DeveloperError('url is required.');
        }

        var dataSource = this;
        return loadJson(url).then(function(geoJson) {
            dataSource.load(geoJson);
        }, function(error) {
            this._error.raiseEvent(this, error);
        });
    };

    return GeoJsonDataSource;
});<commit_msg>Apply default styles to all GeoJSON features.<commit_after>/*global define*/
define(['../Core/createGuid',
        '../Core/Cartographic',
        '../Core/Color',
        '../Core/DeveloperError',
        '../Core/Ellipsoid',
        '../Core/Event',
        '../Core/loadJson',
        './DynamicPoint',
        './DynamicPolyline',
        './DynamicPolygon',
        './DynamicMaterialProperty',
        './DynamicObjectCollection',
        './StaticProperty',
        './StaticPositionProperty'
        ], function(
                createGuid,
                Cartographic,
                Color,
                DeveloperError,
                Ellipsoid,
                Event,
                loadJson,
                DynamicPoint,
                DynamicPolyline,
                DynamicPolygon,
                DynamicMaterialProperty,
                DynamicObjectCollection,
                StaticProperty,
                StaticPositionProperty) {
    "use strict";

    function applyPointDefaults(dynamicObject) {
        var point = new DynamicPoint();
        point.color = new StaticProperty(Color.BLUE);
        point.pixelSize = new StaticProperty(10);
        point.outlineColor = new StaticProperty(Color.BLACK);
        point.outlineWidth = new StaticProperty(1);
        dynamicObject.point = point;
    }

    function applyPolylineDefaults(dynamicObject) {
        var polyline = new DynamicPolyline();
        polyline.color = new StaticProperty(Color.BLUE);
        polyline.width = new StaticProperty(2);
        polyline.outlineColor = new StaticProperty(Color.BLACK);
        polyline.outlineWidth = new StaticProperty(1);
        dynamicObject.polyline = polyline;
    }

    var staticColorCzml = {
        solidColor : {
            color : {
                rgba : [0, 0, 255, 25.5]
            }
        }
    };

    var material = new DynamicMaterialProperty();
    material.processCzmlIntervals(staticColorCzml, undefined, undefined);

    function applyPolygonDefaults(dynamicObject) {
        var polyline = new DynamicPolyline();
        polyline.color = new StaticProperty(Color.BLUE);
        polyline.width = new StaticProperty(1);
        polyline.outlineColor = new StaticProperty(Color.BLACK);
        polyline.outlineWidth = new StaticProperty(0);
        dynamicObject.polyline = polyline;

        var polygon = new DynamicPolygon();
        polygon.material = material;
        dynamicObject.polygon = polygon;
    }

    function processFeature(feature, dynamicObjectCollection) {
        processors[feature.geometry.type](feature, dynamicObjectCollection);
    }

    function processFeatureCollection(featureCollection, dynamicObjectCollection) {
        var features = featureCollection.features;
        for ( var i = 0, len = features.length; i < len; i++) {
            var feature = features[i];
            processors[feature.type](feature, dynamicObjectCollection);
        }
    }

    function processGeometryCollection(geometryCollection, dynamicObjectCollection) {
        var geometries = geometryCollection.geometries;
        for ( var i = 0, len = geometries.length; i < len; i++) {
            var geometry = geometries[i];
            processors[geometry.type](geometry, dynamicObjectCollection);
        }
    }

    function processLineString(feature, dynamicObjectCollection) {
        var id = feature.id;
        if (typeof id === 'undefined') {
            id = createGuid();
        }
        var dynamicObject = dynamicObjectCollection.getOrCreateObject(id);
        dynamicObject.feature = feature;

        var coordinates = feature.geometry.coordinates;
        var positions = new Array(coordinates.length);
        for ( var i = 0; i < coordinates.length; i++) {
            positions[i] = Cartographic.fromDegrees(coordinates[i][0], coordinates[i][1]);
        }
        dynamicObject.vertexPositions = new StaticPositionProperty(Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions));
        applyPolylineDefaults(dynamicObject);
    }

    function processMultiLineString(feature, dynamicObjectCollection) {
        var lineStrings = feature.geometry.coordinates;
        for ( var i = 0; i < lineStrings.length; i++) {
            var lineString = lineStrings[i];
            var dynamicObject = dynamicObjectCollection.getOrCreateObject(createGuid());
            dynamicObject.feature = feature;

            for ( var q = 0; q < lineString.length; q++) {
                var positions = new Array(lineString.length);
                var index = 0;
                for ( var z = 0; z < lineString.length; z++) {
                    positions[index++] = Cartographic.fromDegrees(lineString[i][0], lineString[i][1]);
                }
                dynamicObject.vertexPositions = new StaticPositionProperty(Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions));
                applyPolylineDefaults(dynamicObject);
            }
        }
    }

    function processMultiPoint(feature, dynamicObjectCollection) {
        var coordinates = feature.geometry.coordinates;
        for ( var i = 0; i < coordinates.length; i++) {
            var dynamicObject = dynamicObjectCollection.getOrCreateObject(createGuid());
            dynamicObject.feature = feature;

            var position = Cartographic.fromDegrees(coordinates[i][0], coordinates[i][1]);
            dynamicObject.position = new StaticPositionProperty(Ellipsoid.WGS84.cartographicToCartesian(position));
            applyPointDefaults(dynamicObject);
        }
    }

    function processMultiPolygon(feature, dynamicObjectCollection) {
        var polygons = feature.geometry.coordinates;
        for ( var i = 0; i < polygons.length; i++) {
            var polygon = polygons[i];
            var dynamicObject = dynamicObjectCollection.getOrCreateObject(createGuid());
            dynamicObject.feature = feature;

            //TODO holes
            var vertexPositions = polygon[0];
            for ( var q = 0; q < vertexPositions.length; q++) {
                var positions = new Array(vertexPositions.length);
                var index = 0;
                for ( var z = 0; z < vertexPositions.length; z++) {
                    positions[index++] = Cartographic.fromDegrees(vertexPositions[i][0], vertexPositions[i][1]);
                }
                dynamicObject.vertexPositions = new StaticPositionProperty(Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions));
                applyPolygonDefaults(dynamicObject);
            }
        }
    }

    function processPoint(feature, dynamicObjectCollection) {
        var id = feature.id;
        if (typeof id === 'undefined') {
            id = createGuid();
        }
        var dynamicObject = dynamicObjectCollection.getOrCreateObject(id);
        dynamicObject.feature = feature;

        var coordinates = feature.geometry.coordinates;
        var position = Cartographic.fromDegrees(coordinates[0], coordinates[1]);
        dynamicObject.position = new StaticPositionProperty(Ellipsoid.WGS84.cartographicToCartesian(position));
        applyPointDefaults(dynamicObject);
    }

    function processPolygon(feature, dynamicObjectCollection) {
        var id = feature.id;
        if (typeof id === 'undefined') {
            id = createGuid();
        }
        var dynamicObject = dynamicObjectCollection.getOrCreateObject(id);
        dynamicObject.feature = feature;

        //TODO Holes
        var coordinates = feature.geometry.coordinates[0];
        var positions = new Array(coordinates.length);
        var index = 0;
        for ( var i = 0; i < coordinates.length; i++) {
            positions[index++] = Cartographic.fromDegrees(coordinates[i][0], coordinates[i][1]);
        }
        dynamicObject.vertexPositions = new StaticPositionProperty(Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions));
        applyPolygonDefaults(dynamicObject);
    }

    var processors = {
        Feature : processFeature,
        FeatureCollection : processFeatureCollection,
        GeometryCollection : processGeometryCollection,
        LineString : processLineString,
        MultiLineString : processMultiLineString,
        MultiPoint : processMultiPoint,
        MultiPolygon : processMultiPolygon,
        Point : processPoint,
        Polygon : processPolygon
    };

    var GeoJsonDataSource = function() {
        this._changed = new Event();
        this._error = new Event();
        this._dynamicObjectCollection = new DynamicObjectCollection();
    };

    GeoJsonDataSource.prototype.getChangedEvent = function() {
        return this._changed;
    };

    GeoJsonDataSource.prototype.getErrorEvent = function() {
        return this._error;
    };

    GeoJsonDataSource.prototype.getClock = function() {
        return undefined;
    };

    GeoJsonDataSource.prototype.getDynamicObjectCollection = function() {
        return this._dynamicObjectCollection;
    };

    GeoJsonDataSource.prototype.getIsTimeVarying = function() {
        return false;
    };

    GeoJsonDataSource.prototype.load = function(geoJson) {
        if (typeof geoJson === 'undefined') {
            throw new DeveloperError('geoJson is required.');
        }

        this._dynamicObjectCollection.clear();

        if (typeof geoJson.type === 'undefined') {
            throw new DeveloperError('Invalid GeoJSON.  Type not defined');
        }

        var callback = processors[geoJson.type];
        if (typeof callback === 'undefined') {
            throw new DeveloperError('Unsupported feature type: ' + geoJson.type);
        }
        callback(geoJson, this._dynamicObjectCollection);
    };

    GeoJsonDataSource.prototype.loadUrl = function(url) {
        if (typeof url === 'undefined') {
            throw new DeveloperError('url is required.');
        }

        var dataSource = this;
        return loadJson(url).then(function(geoJson) {
            dataSource.load(geoJson);
        }, function(error) {
            this._error.raiseEvent(this, error);
        });
    };

    return GeoJsonDataSource;
});<|endoftext|>


<commit_before>import React, {Component} from 'react';

import IconButton from 'src/IconButton';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'assets/propTypes/Widget.json';

import 'sass/containers/app/modules/layout/WidgetExamples.scss';

export default class WidgetExamples extends Component {

    constructor(props) {
        super(props);
    }

    render() {
        return (

Widget

                    A Widget element is a basic container that can give a title.

Examples

                <Widget>

                    <WidgetHeader className="example-header" title="Widget Example"/>

Widget example showing title and content.Set the value of the title property to
                                    'Title' and place the content in the widget-content container.

                                <Widget>

                                    <WidgetHeader title="Title">
                                        <IconButton iconCls="far fa-thumbs-up"/>
                                        <IconButton iconCls="fas fa-trash-alt"/>
                                    </WidgetHeader>

                                        widget content

                                </Widget>

                </Widget>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
};<commit_msg>update WidgetExamples<commit_after>import React, {Component} from 'react';

import IconButton from 'src/IconButton';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'assets/propTypes/Widget.json';

import 'sass/containers/app/modules/layout/WidgetExamples.scss';

class WidgetExamples extends Component {

    constructor(props) {
        super(props);
    }

    render() {
        return (

Widget

                    A Widget element is a basic container that can give a title.

Examples

                <Widget>

                    <WidgetHeader className="example-header" title="Widget Example"/>

Widget example showing title and content.Set the value of the title property to
                                    'Title' and place the content in the widget-content container.

                                <Widget>

                                    <WidgetHeader title="Title">
                                        <IconButton iconCls="far fa-thumbs-up"/>
                                        <IconButton iconCls="fas fa-trash-alt"/>
                                    </WidgetHeader>

                                        widget content

                                </Widget>

                </Widget>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
};

export default WidgetExamples;<|endoftext|>


<commit_before>(function() {

'use strict';

// requires jQuery, and a task object in the global scope.

// this should be called before the task loads, because the task can modify
// its html at load, and we want to return unmodified html in getTaskResources.
var res = {};

var taskResourcesLoaded = false;

window.implementGetResources = function(task) {
   task.getResources = function(callback)
   {
      if (taskResourcesLoaded) {
         callback(res);
         return;
      }
      res.task = ('task' in res) ? res.task : [{ type: 'html', content: $('#task').html() }];
      res.solution = ('solution' in res) ? res.solution : [{ type: 'html', content: $('#solution').html() }];
      res.grader = [];
      res.task_modules = [];
      res.solution_modules = [];
      res.grader_modules = [];
      if (!res.hints) {
         res.hints = [];
         $('.hint').each(function(index) {
            res.hints[res.hints.length] = [{type: 'html', content: $(this).html() }];
            $(this).attr('hint-Num', res.hints.length-1);
         });
      }
      res.proxy = [];
      res.proxy_modules = [];
      res.display = [];
      res.display_modules = [];
      res.sat = [];
      res.sat_modules = [];
      res.files = [];
      if (!res.title) {
         res.title = $('title').text();
      }

      // Resources
      var curDest = 'task';
      var curType = 'javascript';
      $('script, style, link').each(function() {
         if ($(this).hasClass('remove')) {
            return;
         }
         if ($(this).hasClass('solution') && $(this).hasClass('module')) {
            curDest = res.solution_modules;
         }
         else if ($(this).hasClass('solution')) {
            curDest = res.solution;
         }
         else if ($(this).hasClass('grader') && $(this).hasClass('module')) {
            curDest = res.grader_modules;
         }
         else if ($(this).hasClass('grader')) {
            curDest = res.grader;
         }
         else if ($(this).hasClass('hint')) {
            res.hints.push([{ type: 'html', content: $(this).html() }]);
            return;
         }
         else if ($(this).hasClass('proxy') && $(this).hasClass('module')) {
            curDest = res.proxy_modules;
         }
         else if ($(this).hasClass('proxy')) {
            curDest = res.proxy;
         }
         else if ($(this).hasClass('stdButtonsAndMessages') && $(this).hasClass('module')) {
            curDest = res.display_modules;
         }
         else if ($(this).hasClass('stdButtonsAndMessages')) {
            curDest = res.display;
         }
         else if ($(this).hasClass('stdAnswerTypes') && $(this).hasClass('module')) {
            curDest = res.sat_modules;
         }
         else if ($(this).hasClass('stdAnswerTypes')) {
            curDest = res.sat;
         }
         else if ($(this).hasClass('module')) {
            curDest = res.task_modules;
         }
         else {
            curDest = res.task;
         }

         if ($(this).is('script')) {
            curType = 'javascript';
         }
         else if ($(this).is('style') || $(this).is('link')) {
            curType = 'css';
         }

         if ($(this).attr('src')) {
            curDest.push({ type: curType, url: $(this).attr('src'), id: $(this).attr('id') });
         }
         else if ($(this).attr('href')) {
            curDest.push({ type: curType, url: $(this).attr('href'), id: $(this).attr('id') });
         }
         else {
            curDest.push({ type: curType, id: $(this).attr('id'), content: $(this).html() });
         }
      });

      // Images
      var images = [];
      var image = '';
      $('#task img').each(function() {
         var src = $(this).attr('src');
         if (src) {
            image = src.toString();
            if ($.inArray(image, images) === -1) {
               res.task.push({ type: 'image', url: image });
               images.push(image);
            }
         }
      });
      fillImages($('#task').html(), images, res.task);
      $('script').each(function() {
         if ($(this).hasClass('remove') || $(this).attr('src') || $(this).attr('href')) {
            return;
         }
         fillImages($(this).html(), images, res.task);
      });
      $('#solution img').each(function() {
         image = $(this).attr('src').toString();
         if ($.inArray(image, images) === -1) {
            res.solution.push({ type: 'image', url: image });
            images.push(image);
         }
      });
      fillImages($('#solution').html(), images, res.solution);
      $('.hint').each(function() {
         var hintnum = $(this).attr('hint-num');
         $('[hint-num='+hintnum+'] img').each(function() {
            image = $(this).attr('src').toString();
            if ($.inArray(image, images) === -1) {
               res.hints[hintnum].push({ type: 'image', url: image });
               images.push(image);
            }
         });
         fillImages($(this).html(), images, res.hints[hintnum]);
      });

      // Links
      $('iframe').each(function () {
        var curUrl = $(this).attr('src');
        if(curUrl.indexOf('://') == -1 && curUrl.charAt(0) != '/') {
          res.files.push({ type: this.tagName, url: $(this).attr('src') });
        }
      });

      // Other resources
      $('source, track').each(function() {
        res.files.push({ type: this.tagName, url: $(this).attr('src') });
      });
      $('fioi-video-player').each(function() {
        var fileAttributes = ["data-source", "data-image", "data-subtitles"];
        for(var i=0; i<fileAttributes.length; i++) {
           var curAttr = $(this).attr(fileAttributes[i]);
           curAttr = curAttr ? curAttr.split(';') : [];
           for(var a=0; a<curAttr.length; a++) {
              var curAttrFile = curAttr[a];
              if(curAttrFile && curAttrFile != 'animation' && curAttrFile != 'none') {
                 res.files.push({ type: fileAttributes[i], url: curAttrFile });
              }
           }
        }
      });

      taskResourcesLoaded = true;
      callback(res);
   };
}

function declareResource(type, resource) {
   if (!res[type]) {
      res[type] = [];
   }
   res[type].push(resource);
}

window.declareTaskResource = declareResource;

var resourcesObjectForRegistration = {};

$(document).ready(function() {
   if (typeof json !== 'undefined') {
      res = json;
   }

   if(window.preprocessingFunctions) {
      for(var i=0; i<window.preprocessingFunctions.length; i++) {
         window.preprocessingFunctions[i]();
      }
   }
   window.preprocessingFunctions = [];

   res.hints = [];
   $('.hint').each(function(index) {
      res.hints[res.hints.length] = [{type: 'html', content: $(this).html() }];
      $(this).attr('hint-num', res.hints.length-1);
   });
   res.task = [{ type: 'html', content: $('#task').html() }];
   res.solution = [{ type: 'html', content: $('#solution').html() }];
   if (window.task) {
      window.implementGetResources(window.task);
      // alias for old code, TODO: remove
      window.getTaskResources = task.getResources;
   }
});

function fillImages(text, images, res) {
   var extensions = ["png", "jpg", "gif", "ttf", "woff", "eot"];
   for (var iExt = 0; iExt < extensions.length; iExt++) {
      var ext = extensions[iExt];
      var regexp = new RegExp("[\'\"]([^;\"\']*." + ext + ")[\'\"]", "g");
      while (true) {
         var match = regexp.exec(text);
         if (!match) {
            break;
         }
         var image = match[1];
         if (image.length <= ext.length + 1) {
            continue;
         }
         if ($.inArray(image, images) === -1) {
            res.push({ type: 'image', url: image });
            images.push(image);
         }
      }
   }
}

})();
<commit_msg>support mp4<commit_after>(function() {

'use strict';

// requires jQuery, and a task object in the global scope.

// this should be called before the task loads, because the task can modify
// its html at load, and we want to return unmodified html in getTaskResources.
var res = {};

var taskResourcesLoaded = false;

window.implementGetResources = function(task) {
   task.getResources = function(callback)
   {
      if (taskResourcesLoaded) {
         callback(res);
         return;
      }
      res.task = ('task' in res) ? res.task : [{ type: 'html', content: $('#task').html() }];
      res.solution = ('solution' in res) ? res.solution : [{ type: 'html', content: $('#solution').html() }];
      res.grader = [];
      res.task_modules = [];
      res.solution_modules = [];
      res.grader_modules = [];
      if (!res.hints) {
         res.hints = [];
         $('.hint').each(function(index) {
            res.hints[res.hints.length] = [{type: 'html', content: $(this).html() }];
            $(this).attr('hint-Num', res.hints.length-1);
         });
      }
      res.proxy = [];
      res.proxy_modules = [];
      res.display = [];
      res.display_modules = [];
      res.sat = [];
      res.sat_modules = [];
      res.files = [];
      if (!res.title) {
         res.title = $('title').text();
      }

      // Resources
      var curDest = 'task';
      var curType = 'javascript';
      $('script, style, link').each(function() {
         if ($(this).hasClass('remove')) {
            return;
         }
         if ($(this).hasClass('solution') && $(this).hasClass('module')) {
            curDest = res.solution_modules;
         }
         else if ($(this).hasClass('solution')) {
            curDest = res.solution;
         }
         else if ($(this).hasClass('grader') && $(this).hasClass('module')) {
            curDest = res.grader_modules;
         }
         else if ($(this).hasClass('grader')) {
            curDest = res.grader;
         }
         else if ($(this).hasClass('hint')) {
            res.hints.push([{ type: 'html', content: $(this).html() }]);
            return;
         }
         else if ($(this).hasClass('proxy') && $(this).hasClass('module')) {
            curDest = res.proxy_modules;
         }
         else if ($(this).hasClass('proxy')) {
            curDest = res.proxy;
         }
         else if ($(this).hasClass('stdButtonsAndMessages') && $(this).hasClass('module')) {
            curDest = res.display_modules;
         }
         else if ($(this).hasClass('stdButtonsAndMessages')) {
            curDest = res.display;
         }
         else if ($(this).hasClass('stdAnswerTypes') && $(this).hasClass('module')) {
            curDest = res.sat_modules;
         }
         else if ($(this).hasClass('stdAnswerTypes')) {
            curDest = res.sat;
         }
         else if ($(this).hasClass('module')) {
            curDest = res.task_modules;
         }
         else {
            curDest = res.task;
         }

         if ($(this).is('script')) {
            curType = 'javascript';
         }
         else if ($(this).is('style') || $(this).is('link')) {
            curType = 'css';
         }

         if ($(this).attr('src')) {
            curDest.push({ type: curType, url: $(this).attr('src'), id: $(this).attr('id') });
         }
         else if ($(this).attr('href')) {
            curDest.push({ type: curType, url: $(this).attr('href'), id: $(this).attr('id') });
         }
         else {
            curDest.push({ type: curType, id: $(this).attr('id'), content: $(this).html() });
         }
      });

      // Images
      var images = [];
      var image = '';
      $('#task img').each(function() {
         var src = $(this).attr('src');
         if (src) {
            image = src.toString();
            if ($.inArray(image, images) === -1) {
               res.task.push({ type: 'image', url: image });
               images.push(image);
            }
         }
      });
      fillImages($('#task').html(), images, res.task);
      $('script').each(function() {
         if ($(this).hasClass('remove') || $(this).attr('src') || $(this).attr('href')) {
            return;
         }
         fillImages($(this).html(), images, res.task);
      });
      $('#solution img').each(function() {
         image = $(this).attr('src').toString();
         if ($.inArray(image, images) === -1) {
            res.solution.push({ type: 'image', url: image });
            images.push(image);
         }
      });
      fillImages($('#solution').html(), images, res.solution);
      $('.hint').each(function() {
         var hintnum = $(this).attr('hint-num');
         $('[hint-num='+hintnum+'] img').each(function() {
            image = $(this).attr('src').toString();
            if ($.inArray(image, images) === -1) {
               res.hints[hintnum].push({ type: 'image', url: image });
               images.push(image);
            }
         });
         fillImages($(this).html(), images, res.hints[hintnum]);
      });

      // Links
      $('iframe').each(function () {
        var curUrl = $(this).attr('src');
        if(curUrl.indexOf('://') == -1 && curUrl.charAt(0) != '/') {
          res.files.push({ type: this.tagName, url: $(this).attr('src') });
        }
      });

      // Other resources
      $('source, track').each(function() {
        res.files.push({ type: this.tagName, url: $(this).attr('src') });
      });
      $('fioi-video-player').each(function() {
        var fileAttributes = ["data-source", "data-image", "data-subtitles"];
        for(var i=0; i<fileAttributes.length; i++) {
           var curAttr = $(this).attr(fileAttributes[i]);
           curAttr = curAttr ? curAttr.split(';') : [];
           for(var a=0; a<curAttr.length; a++) {
              var curAttrFile = curAttr[a];
              if(curAttrFile && curAttrFile != 'animation' && curAttrFile != 'none') {
                 res.files.push({ type: fileAttributes[i], url: curAttrFile });
              }
           }
        }
      });

      taskResourcesLoaded = true;
      callback(res);
   };
}

function declareResource(type, resource) {
   if (!res[type]) {
      res[type] = [];
   }
   res[type].push(resource);
}

window.declareTaskResource = declareResource;

var resourcesObjectForRegistration = {};

$(document).ready(function() {
   if (typeof json !== 'undefined') {
      res = json;
   }

   if(window.preprocessingFunctions) {
      for(var i=0; i<window.preprocessingFunctions.length; i++) {
         window.preprocessingFunctions[i]();
      }
   }
   window.preprocessingFunctions = [];

   res.hints = [];
   $('.hint').each(function(index) {
      res.hints[res.hints.length] = [{type: 'html', content: $(this).html() }];
      $(this).attr('hint-num', res.hints.length-1);
   });
   res.task = [{ type: 'html', content: $('#task').html() }];
   res.solution = [{ type: 'html', content: $('#solution').html() }];
   if (window.task) {
      window.implementGetResources(window.task);
      // alias for old code, TODO: remove
      window.getTaskResources = task.getResources;
   }
});

function fillImages(text, images, res) {
   var extensions = ["png", "jpg", "gif", "ttf", "woff", "eot", "mp4"];
   for (var iExt = 0; iExt < extensions.length; iExt++) {
      var ext = extensions[iExt];
      var regexp = new RegExp("[\'\"]([^;\"\']*." + ext + ")[\'\"]", "g");
      while (true) {
         var match = regexp.exec(text);
         if (!match) {
            break;
         }
         var image = match[1];
         if (image.length <= ext.length + 1) {
            continue;
         }
         if ($.inArray(image, images) === -1) {
            res.push({ type: 'image', url: image });
            images.push(image);
         }
      }
   }
}

})();
<|endoftext|>


<commit_before>/*©agpl*************************************************************************
*                                                                              *
* Friend Unifying Platform                                                     *
* ------------------------                                                     *
*                                                                              *
* Copyright 2014-2017 Friend Software Labs AS, all rights reserved.            *
* Hillevaagsveien 14, 4016 Stavanger, Norway                                   *
* Tel.: (+47) 40 72 96 56                                                      *
* Mail: info@friendos.com                                                      *
*                                                                              *
*****************************************************************************©*/

Application.proxy = '';
Application.friendsession = '';
Application.run = function( msg )
{
	var v = new View( {
		title:  i18n( 'i18n_wideweb' ),
		width:  1100,
		height: 900
	} );

	v.setMenuItems( [
		{
			name: i18n( 'i18n_file' ),
			items: [
				{
					name: i18n( 'i18n_about_wideweb' ),
					command: 'about'
				},
				{
					name: i18n( 'i18n_quit' ),
					command: 'quit'
				}
			]
		},
		{
			name: i18n( 'i18n_navigate' ),
			items: [
				{
					name: i18n( 'i18n_nav_back' ),
					command: 'navback'
				},
				{
					name: i18n( 'i18n_nav_forward' ),
					command: 'navforward'
				},
				{
					name: i18n( 'i18n_nav_reload' ),
					command: 'reload'
				}
			]
		},
		{
			name: i18n( 'i18n_bookmarks' ),
			items: [
				{
					name: 'Friend Browser Home',
					command: 'navto:about:blank'
				},
				{
					name: 'FriendUP',
					command: 'navto:https://friendup.cloud/'
				},
				{
					name: 'FriendUP Developers',
					command: 'navto:https://developers.friendup.cloud/'
				},
				{
					name: 'Friend Software Corporation',
					command: 'navto:https://friendsoftware.cloud/'
				},
				{
					name: 'Slashdot.org',
					command: 'navto:https://slashdot.org/'
				}
			]
		}/*,
		{
			name: i18n( 'i18n_edit' ),
			items: [
			]
		}*/
	] );

	this.mainView = v;

	v.onClose = function( data )
	{
		Application.quit();
	}

	Application.mainView.setFlag( 'title', i18n( 'i18n_wideweb' ) );
	var f = new File( 'Progdir:Templates/webinterface.html' );
	f.replacements = {
		startupurl: msg.args ? msg.args : ''
	};
	f.onLoad = function( data )
	{
		v.setContent( data, function()
		{
			if( msg.args )
			{
				Application.receiveMessage( {
					command: 'seturl',
					url: msg.args
				} );
			}
		} );
	}
	f.load();

}

Application.receiveMessage = function( msg )
{
	if( !msg.command ) return;

	if( msg.command.substr( 0, 6 ) == 'navto:' )
	{
		var url = msg.command.substr( 6, msg.command.length - 6 );
		msg.command = 'seturl';
		msg.url = url;
	}

	switch( msg.command )
	{
		case 'setcontent':
			Application.mainView.setFlag( 'title', i18n( 'i18n_wideweb' ) + ' - ' + msg.url );
			this.currentUrl = msg.url;
			break;
		case 'seturl':
			if( msg.url.indexOf( 'FriendBrowser/Templates/about.html' ) < 0 && msg.url != this.currentUrl )
			{
				this.currentUrl = msg.url;
				Application.mainView.setFlag( 'title', i18n( 'i18n_wideweb' ) + ' - ' + msg.url );
				// Logic calls do not end up back in the browser window..
				if( !msg.logic )
					this.mainView.sendMessage( { command: 'loadfile', filename: this.currentUrl } );
			}
			break;
		case 'updateproxy':
			Application.mainView.sendMessage( { command: 'setproxy', proxy: Application.proxy, friendsession: Application.friendsession } );
			break;
		case 'reload':
			this.receiveMessage( { command: 'seturl', url: this.currentUrl ? this.currentUrl : "" } );
			this.mainView.sendMessage( { command: 'loadfile', filename: this.currentUrl } );
			break;
		case 'forward':
			this.mainView.sendMessage( { command: 'forward' } );
			break;
		case 'backward':
			this.mainView.sendMessage( { command: 'backward' } );
			break;
		case 'activate_now':
			this.mainView.activate();
			break;
		case 'about':
			if( this.ab )
			{
				return this.ab.activate();
			}
			this.ab = new View( {
				title: i18n( 'i18n_about_wideweb' ),
				width: 300,
				height: 400
			} );
			var f = new File( 'Progdir:Templates/about.html' );
			f.onLoad = function( data )
			{
				Application.ab.setContent( data );
			}
			f.i18n();
			f.load();
			this.ab.onClose = function()
			{
				Application.ab = false;
			}
			break;
		case 'fnet_connect':
			Application.connectToFriend( msg.url );
			break;
	}
}

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

Application.cleanArray = function( keys )
{
	var out = [ ];
	for ( var key in keys )
	{
		if ( keys[ key ] )
			out[ key ] = keys[ key ];
	}
	return out;
};
Application.connectToFriend = function( url )
{
	// Do we have a / at the end of the url?
	var folder, path;
	var pos = url.indexOf( '/' );
	if ( pos > 0 )
	{
		url = url.substring( 0, pos );
		var command = url.substring( pos + 1 );
		if ( command.indexOf( '/' ) >= 0 )
		{
			folder = command.split( '/' )[ 0 ];
			path = command.split( '/' )[ 1 ];
		}
		else
		{
			folder = command;
			path = '';
		}
	}

	// No path, connects to the public page
	if ( !folder || folder == '' )
	{
		folder = 'public';
		path = '';
	}

	// Get the list from FriendNetworkShare
	var self = this;
	FriendNetworkFriends.listCommunities( url, function( message )
	{
		if ( message.response )
		{
			// Only one user?
			if ( message.users.length == 1 && message.communities.length == 1 )
			{
				var user = message.users[ 0 ];

				// Find the shared folder
				for ( var s = 0; s < user.sharing.length; s++ )
				{
					var sharing = user.sharing[ s ];
					if ( sharing.name == folder )
					{
						// Disconnect from previous host
						if ( self.hostName && self.appName )
							FriendNetworkDoor.disconnectFromDoor( self.hostName, self.appName );

						// Connects to new one
						FriendNetworkDoor.connectToDoor( user.name, folder, function( msg )
						{
							if ( msg.response == 'connected' )
							{
								self.connecting = false;
								self.hostName = user.name;
								self.appName = folder;
								self.doorName = msg.connection.doorName;
								self.community = message.communities[ 0 ].name;
								self.mainView.sendMessage
								(
									{
										command: 'fnetConnected',
										hostName: self.hostName,
										appName: self.appName,
										doorName: self.doorName,
										community: self.community,
										path: path
									}
								);
							}
							else
							{
								self.connecting = false;
								self.mainView.sendMessage( { command: 'fnetConnectionFailed' } );
							}
						} );
						return;
					}
				}
			}
			// Other cases-> list!
			self.mainView.sendMessage( { command: 'listCommunities', url: url, communities: message.communities, users: message.users } );
		}
		else
		{
			self.mainView.sendMessage( { command: 'fnetConnectionFailed' } );
		}
	} );
};
<commit_msg>New bookmarks.<commit_after>/*©agpl*************************************************************************
*                                                                              *
* Friend Unifying Platform                                                     *
* ------------------------                                                     *
*                                                                              *
* Copyright 2014-2017 Friend Software Labs AS, all rights reserved.            *
* Hillevaagsveien 14, 4016 Stavanger, Norway                                   *
* Tel.: (+47) 40 72 96 56                                                      *
* Mail: info@friendos.com                                                      *
*                                                                              *
*****************************************************************************©*/

Application.proxy = '';
Application.friendsession = '';
Application.run = function( msg )
{
	var v = new View( {
		title:  i18n( 'i18n_wideweb' ),
		width:  1100,
		height: 900
	} );

	v.setMenuItems( [
		{
			name: i18n( 'i18n_file' ),
			items: [
				{
					name: i18n( 'i18n_about_wideweb' ),
					command: 'about'
				},
				{
					name: i18n( 'i18n_quit' ),
					command: 'quit'
				}
			]
		},
		{
			name: i18n( 'i18n_navigate' ),
			items: [
				{
					name: i18n( 'i18n_nav_back' ),
					command: 'navback'
				},
				{
					name: i18n( 'i18n_nav_forward' ),
					command: 'navforward'
				},
				{
					name: i18n( 'i18n_nav_reload' ),
					command: 'reload'
				}
			]
		},
		{
			name: i18n( 'i18n_bookmarks' ),
			items: [
				{
					name: 'Friend OS Home',
					command: 'navto:https://friendos.com/'
				},
				{
					name: 'Your personal page',
					command: 'navto:about:blank'
				},
				{
					name: 'Friend Nexus Forum',
					command: 'navto:https://friend-nexus.com/'
				},
				{
					name: 'DTube',
					command: 'navto:https://d.tube/'
				}
			]
		}/*,
		{
			name: i18n( 'i18n_edit' ),
			items: [
			]
		}*/
	] );

	this.mainView = v;

	v.onClose = function( data )
	{
		Application.quit();
	}

	Application.mainView.setFlag( 'title', i18n( 'i18n_wideweb' ) );
	var f = new File( 'Progdir:Templates/webinterface.html' );
	f.replacements = {
		startupurl: msg.args ? msg.args : ''
	};
	f.onLoad = function( data )
	{
		v.setContent( data, function()
		{
			if( msg.args )
			{
				Application.receiveMessage( {
					command: 'seturl',
					url: msg.args
				} );
			}
		} );
	}
	f.load();

}

Application.receiveMessage = function( msg )
{
	if( !msg.command ) return;

	if( msg.command.substr( 0, 6 ) == 'navto:' )
	{
		var url = msg.command.substr( 6, msg.command.length - 6 );
		msg.command = 'seturl';
		msg.url = url;
	}

	switch( msg.command )
	{
		case 'setcontent':
			Application.mainView.setFlag( 'title', i18n( 'i18n_wideweb' ) + ' - ' + msg.url );
			this.currentUrl = msg.url;
			break;
		case 'seturl':
			if( msg.url.indexOf( 'FriendBrowser/Templates/about.html' ) < 0 && msg.url != this.currentUrl )
			{
				this.currentUrl = msg.url;
				Application.mainView.setFlag( 'title', i18n( 'i18n_wideweb' ) + ' - ' + msg.url );
				// Logic calls do not end up back in the browser window..
				if( !msg.logic )
					this.mainView.sendMessage( { command: 'loadfile', filename: this.currentUrl } );
			}
			break;
		case 'updateproxy':
			Application.mainView.sendMessage( { command: 'setproxy', proxy: Application.proxy, friendsession: Application.friendsession } );
			break;
		case 'reload':
			this.receiveMessage( { command: 'seturl', url: this.currentUrl ? this.currentUrl : "" } );
			this.mainView.sendMessage( { command: 'loadfile', filename: this.currentUrl } );
			break;
		case 'forward':
			this.mainView.sendMessage( { command: 'forward' } );
			break;
		case 'backward':
			this.mainView.sendMessage( { command: 'backward' } );
			break;
		case 'activate_now':
			this.mainView.activate();
			break;
		case 'about':
			if( this.ab )
			{
				return this.ab.activate();
			}
			this.ab = new View( {
				title: i18n( 'i18n_about_wideweb' ),
				width: 300,
				height: 400
			} );
			var f = new File( 'Progdir:Templates/about.html' );
			f.onLoad = function( data )
			{
				Application.ab.setContent( data );
			}
			f.i18n();
			f.load();
			this.ab.onClose = function()
			{
				Application.ab = false;
			}
			break;
		case 'fnet_connect':
			Application.connectToFriend( msg.url );
			break;
	}
}

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

Application.cleanArray = function( keys )
{
	var out = [ ];
	for ( var key in keys )
	{
		if ( keys[ key ] )
			out[ key ] = keys[ key ];
	}
	return out;
};
Application.connectToFriend = function( url )
{
	// Do we have a / at the end of the url?
	var folder, path;
	var pos = url.indexOf( '/' );
	if ( pos > 0 )
	{
		url = url.substring( 0, pos );
		var command = url.substring( pos + 1 );
		if ( command.indexOf( '/' ) >= 0 )
		{
			folder = command.split( '/' )[ 0 ];
			path = command.split( '/' )[ 1 ];
		}
		else
		{
			folder = command;
			path = '';
		}
	}

	// No path, connects to the public page
	if ( !folder || folder == '' )
	{
		folder = 'public';
		path = '';
	}

	// Get the list from FriendNetworkShare
	var self = this;
	FriendNetworkFriends.listCommunities( url, function( message )
	{
		if ( message.response )
		{
			// Only one user?
			if ( message.users.length == 1 && message.communities.length == 1 )
			{
				var user = message.users[ 0 ];

				// Find the shared folder
				for ( var s = 0; s < user.sharing.length; s++ )
				{
					var sharing = user.sharing[ s ];
					if ( sharing.name == folder )
					{
						// Disconnect from previous host
						if ( self.hostName && self.appName )
							FriendNetworkDoor.disconnectFromDoor( self.hostName, self.appName );

						// Connects to new one
						FriendNetworkDoor.connectToDoor( user.name, folder, function( msg )
						{
							if ( msg.response == 'connected' )
							{
								self.connecting = false;
								self.hostName = user.name;
								self.appName = folder;
								self.doorName = msg.connection.doorName;
								self.community = message.communities[ 0 ].name;
								self.mainView.sendMessage
								(
									{
										command: 'fnetConnected',
										hostName: self.hostName,
										appName: self.appName,
										doorName: self.doorName,
										community: self.community,
										path: path
									}
								);
							}
							else
							{
								self.connecting = false;
								self.mainView.sendMessage( { command: 'fnetConnectionFailed' } );
							}
						} );
						return;
					}
				}
			}
			// Other cases-> list!
			self.mainView.sendMessage( { command: 'listCommunities', url: url, communities: message.communities, users: message.users } );
		}
		else
		{
			self.mainView.sendMessage( { command: 'fnetConnectionFailed' } );
		}
	} );
};
<|endoftext|>