domingo, 14 de septiembre de 2014

5 - Agenda

Agenda sesión #5

1 - Resumen de lo visto hasta ahora (20')
2 - Procedimiento para realizar operaciones básicas con JavaScript en SharePoint 2013 (100')
Break
3 - App Contoso (Provider Hosted-App). Uso de Azure (120')

5.2.8.3 - Eliminar un elemento de lista

Eliminar un elemento de lista

Para eliminar un elemento de lista, se llama a la función deleteObject() del objeto. En el siguiente ejemplo se usa la función getItemById(id) para devolver el segundo elemento de la lista y luego se elimina el elemento.
SharePoint mantiene los identificadores de enteros de los elementos dentro de las colecciones aunque se hayan eliminado.
Por ejemplo, el segundo elemento de una lista podría no tener el 2 como identificador. Si se llama a la función deleteObject() para un elemento que no existe, se devuelve la excepción ServerException.

function deleteListItem(siteUrl) {
    this.itemId = 2;
    var clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');
    this.oListItem = oList.getItemById(itemId);
    oListItem.deleteObject();

    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded() {
    alert('Item deleted: ' + itemId);
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}


Por ejemplo, si desea recuperar el nuevo recuento de elementos que resulta de una operación de eliminación, se incluye una llamada al método update() para actualizar la lista. Además, debe cargar el objeto de lista en sí o la propiedad itemCount en el objeto de lista antes de ejecutar la consulta. Si desea recuperar un recuento de inicio y finalización de los elementos de lista, debe ejecutar dos consultas y devolver el recuento de elemento dos veces, tal como se muestra en la modificación siguiente del ejemplo anterior.

function deleteListItemDisplayCount(siteUrl) {
    this.clientContext = new SP.ClientContext(siteUrl);
    this.oList = clientContext.get_web().get_lists()
                         .getByTitle('Announcements');
    clientContext.load(oList);

    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.deleteItem), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function deleteItem() {
    this.itemId = 58;
    this.startCount = oList.get_itemCount();
    this.oListItem = oList.getItemById(itemId);
    oListItem.deleteObject();

    oList.update();
    clientContext.load(oList);
        
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.displayCount), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function displayCount() {
    var endCount = oList.get_itemCount();
    var listItemInfo = 'Item deleted: ' + itemId + 
        '\nStart Count: ' +  startCount + 
        ' End Count: ' + endCount;
        
    alert(listItemInfo)
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

5.2.8.2 - Actualizar un elemento de lista

Actualizar un elemento de lista

Para establecer la mayoría de las propiedades del elemento de lista, se puede usar un indizador de columna para realizar una asignación y llamar a la función update() para que los cambios se realicen al llamar a executeQueryAsync(succeededCallback, failedCallback).
En el ejemplo siguiente se establece el título del tercer elemento de la lista de anuncios.

function updateListItem(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');

    this.oListItem = oList.getItemById(3);
    oListItem.set_item('Title', 'My Updated Title');
    oListItem.update();

    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded() {
    alert('Item updated!');
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

5.2.8.1 - Crear, actualizar y eliminar elementos de lista

Crear, actualizar y eliminar elementos de lista

La creación, actualización o eliminación de elementos de lista mediante el modelo de objetos de cliente funciona de forma similar a la realización de tareas mediante el modelo de objetos de servidor. Se crea un objeto de elemento de lista, se establecen sus propiedades y, a continuación, se actualiza el objeto.
Para modificar o eliminar un objeto de elemento de lista, se usa la función getById(id) del objeto ListItemCollection para devolver el objeto y, a continuación, se establecen las propiedades y llame a la actualización del objeto que devuelve este método o llame al propio método del objeto para eliminarlo. A diferencia del modelo de objetos de servidor, cada una de estas operaciones en el modelo de objetos de cliente debe concluir con una llamada a executeQueryAsync(succeededCallback, failedCallback) para realizar los cambios en el servidor.

Crear un elemento de lista

Para crear elementos de lista, debe crear un objeto ListItemCreationInformation, establecer sus propiedades y pasarlo como parámetro a la función addItem(parameters) del objeto List. Establezca las propiedades en el objeto de elemento de lista que este método devuelve y luego llame a la función update(), como se ve en el ejemplo siguiente.

function createListItem(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');
        
    var itemCreateInfo = new SP.ListItemCreationInformation();
    this.oListItem = oList.addItem(itemCreateInfo);
    oListItem.set_item('Title', 'My New Item!');
    oListItem.set_item('Body', 'Hello World!');
    oListItem.update();

    clientContext.load(oListItem);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded() {
    alert('Item created: ' + oListItem.get_id());
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

5.2.7.2 - Tareas de elementos de lista de SharePoint

Usar el método Include para obtener acceso a propiedades de objetos ListItem

Hay 4 propiedades de objetos ListItem que no están disponibles de forma predeterminada al devolver elementos de lista: displayName, effectiveBasePermissions, hasUniqueRoleAssignments y roleAssignments. El ejemplo anterior devuelve una excepción PropertyOrFieldNotInitializedException si trata de obtener acceso a una de estas propiedades. Para obtener acceso a una de estas propiedades, se debe usar el método Include como parte de la cadena de la consulta, como se muestra en el siguiente ejemplo.

Nota

Al usar LINQ para crear consultas respecto del modelo de objetos de cliente, se utiliza LINQ to Objects, y no el proveedor LINQ to SharePoint, que solo se puede usar cuando se escribe código respecto al modelo de objetos de servidor.

function retrieveListItemsInclude(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');

    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml('<View><RowLimit>100</RowLimit></View>');
    this.collListItem = oList.getItems(camlQuery);

    clientContext.load(
        collListItem, 
        'Include(Id, DisplayName, HasUniqueRoleAssignments)'
    );
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded(sender, args) {
    var listItemInfo = '';
    var listItemEnumerator = collListItem.getEnumerator();
        
    while (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();
        listItemInfo += '\nID: ' + oListItem.get_id() + 
            '\nDisplay name: ' + oListItem.get_displayName() + 
            '\nUnique role assignments: ' + 
            oListItem.get_hasUniqueRoleAssignments();
    }

    alert(listItemInfo.toString());
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}


Dado que en este ejemplo se usa Include, solo las propiedades especificadas estarán disponibles después de la ejecución de la consulta. Por lo tanto, recibirá una excepciónPropertyOrFieldNotInitializedException si trata de obtener acceso a otras propiedades además de las que se especificaron. Además, se recibirá este error si se trata de usar propiedades como get_contentType o get_parentList para obtener acceso a las propiedades de los objetos que contienen.

5.2.7.1 - Tareas de elementos de lista de SharePoint

Tareas de elementos de lista de SharePoint

Para devolver elementos de una lista con JavaScript, se usa la función getItemById(id) para devolver un solo elemento o use la función getItems(query) para devolver varios elementos. Luego se usa la función load(clientObject) para alcanzar los objetos de elemento de lista que representan los elementos.

Recuperar elementos de una lista

La función getItems(query) permite definir una consulta Lenguaje de marcado de aplicaciones de colaboración (CAML) que especifique qué elementos se van a devolver. Puede pasar un objeto CamlQuery no definido para devolver todos los elementos de la lista, o bien usar la función set_viewXml para definir una consulta CAML y devolver los elementos que cumplan con criterios específicos.
En el siguiente ejemplo se muestran los valores de columna Identificador, Título y Cuerpo de los primeros 10 elementos de la lista Anuncios, empezando por los elementos de lista cuyo identificador de colección es mayor que 1.

function retrieveListItems(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');
        
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml(
        '<View><Query><Where><Geq><FieldRef Name=\'ID\'/>' + 
        '<Value Type=\'Number\'>1</Value></Geq></Where></Query>' + 
        '<RowLimit>10</RowLimit></View>'
    );
    this.collListItem = oList.getItems(camlQuery);
        
    clientContext.load(collListItem);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    ); 
}

function onQuerySucceeded(sender, args) {
    var listItemInfo = '';
    var listItemEnumerator = collListItem.getEnumerator();
        
    while (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();
        listItemInfo += '\nID: ' + oListItem.get_id() + 
            '\nTitle: ' + oListItem.get_item('Title') + 
            '\nBody: ' + oListItem.get_item('Body');
    }

    alert(listItemInfo.toString());
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

5.2.6.2 - Crear, leer, actualizar y eliminar archivos

Leer un archivo de una biblioteca de documentos

Para leer el contenido de un archivo, se debe realizar una operación GET en la dirección URL del archivo, como se ve en el ejemplo siguiente.

function readFile(resultpanel) {
    var clientContext;
    var oWebsite;
    var fileUrl;

    clientContext = new SP.ClientContext.get_current();
    oWebsite = clientContext.get_web();

    clientContext.load(oWebsite);
    clientContext.executeQueryAsync(function () {
        fileUrl = oWebsite.get_serverRelativeUrl() +
            "/Lists/Shared Documents/TextFile1.txt";
        $.ajax({
            url: fileUrl,
            type: "GET"
        })
            .done(Function.createDelegate(this, successHandler))
            .error(Function.createDelegate(this, errorHandler));
    }, errorHandler);

    function successHandler(data) {
        resultpanel.innerHTML =
            "The content of file \"TextFile1.txt\": " + data
    }

    function errorHandler() {
        resultpanel.innerHTML =
            "Request failed: " + arguments[2];
    }
}

5.2.6.3 - Crear, leer, actualizar y eliminar archivos

Actualizar un archivo de una biblioteca de documentos

Para actualizar el contenido de un archivo, puede usar un objeto FileCreationInformation y definir el atributo de sobrescritura en true usando el método set_overwrite(), como se ve en este ejemplo.

function updateFile(resultpanel) {
    var clientContext;
    var oWebsite;
    var oList;
    var fileCreateInfo;
    var fileContent;

    clientContext = new SP.ClientContext.get_current();
    oWebsite = clientContext.get_web();
    oList = oWebsite.get_lists().getByTitle("Shared Documents");

    fileCreateInfo = new SP.FileCreationInformation();
    fileCreateInfo.set_url("TextFile1.txt");
    fileCreateInfo.set_content(new SP.Base64EncodedByteArray());
    fileCreateInfo.set_overwrite(true);
    fileContent = "The updated content of my file";

    for (var i = 0; i < fileContent.length; i++) {

        fileCreateInfo.get_content().append(fileContent.charCodeAt(i));
    }

    this.existingFile = oList.get_rootFolder().get_files().add(fileCreateInfo);

    clientContext.load(this.existingFile);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, successHandler),
        Function.createDelegate(this, errorHandler)
    );

    function successHandler() {
        resultpanel.innerHTML =
            "Go to the " +
            "<a href='../Lists/Shared Documents'>document library</a> " +
            "to see the updated \"TextFile1.txt\" file.";
    }

    function errorHandler() {
        resultpanel.innerHTML =
            "Request failed: " + arguments[1].get_message();
    }
}

5.2.6.4 - Crear, leer, actualizar y eliminar archivos

Eliminar un archivo de una biblioteca de documentos

Para eliminar un archivo, llame a la función deleteObject() en el objeto. El ejemplo siguiente usa el método getFileByServerRelativeUrl para recuperar el archivo de la biblioteca de documentos y luego elimina el elemento.

function deleteFile(resultpanel) {
    var clientContext;
    var oWebsite;
    var fileUrl;

    clientContext = new SP.ClientContext.get_current();
    oWebsite = clientContext.get_web();

    clientContext.load(oWebsite);
    clientContext.executeQueryAsync(function () {
        fileUrl = oWebsite.get_serverRelativeUrl() +
            "/Lists/Shared Documents/TextFile1.txt";
        this.fileToDelete = oWebsite.getFileByServerRelativeUrl(fileUrl);
        this.fileToDelete.deleteObject();

        clientContext.executeQueryAsync(
            Function.createDelegate(this, successHandler),
            Function.createDelegate(this, errorHandler)
        );
    }, errorHandler);

    function successHandler() {
        resultpanel.innerHTML =
            "Go to the " +
            "<a href='../Lists/Shared Documents'>document library</a> " +
            "to confirm that the \"TextFile1.txt\" file has been deleted.";
    }

    function errorHandler() {
        resultpanel.innerHTML = "Request failed: " + arguments[1].get_message();
    }
}

5.2.6.1 - Crear, leer, actualizar y eliminar archivos

Crear, leer, actualizar y eliminar archivos

Se pueden manipular archivos usando el modelo de objetos JavaScript. 

Nota Importante

Solo se puede trabajar con archivos de hasta 1,5 MB usando el modelo de objetos JavaScript. Para cargar archivos más grandes, se deberá utilizar REST (transferencia de estado representacional). Lo veremos en las próximas sesiones

Crear un archivo en una biblioteca de documentos

Para crear un archivo, se debe usar un objeto FileCreationInformation, definir el atributo de la dirección URL y anexar contenido como una matriz codificada base64 de bytes, como se ve en este ejemplo.

function createFile(resultpanel) {
    var clientContext;
    var oWebsite;
    var oList;
    var fileCreateInfo;
    var fileContent;

    clientContext = new SP.ClientContext.get_current();
    oWebsite = clientContext.get_web();
    oList = oWebsite.get_lists().getByTitle("Shared Documents");

    fileCreateInfo = new SP.FileCreationInformation();
    fileCreateInfo.set_url("my new file.txt");
    fileCreateInfo.set_content(new SP.Base64EncodedByteArray());
    fileContent = "The content of my new file";

    for (var i = 0; i < fileContent.length; i++) {
        
        fileCreateInfo.get_content().append(fileContent.charCodeAt(i));
    }

    this.newFile = oList.get_rootFolder().get_files().add(fileCreateInfo);

    clientContext.load(this.newFile);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, successHandler),
        Function.createDelegate(this, errorHandler)
    );

    function successHandler() {
        resultpanel.innerHTML =
            "Go to the " +
            "<a href='../Lists/Shared Documents'>document library</a> " +
            "to see your new file.";
    }

    function errorHandler() {
        resultpanel.innerHTML = "Request failed: " + arguments[1].get_message();
    }
}

5.2.5.3 - Crear, actualizar y eliminar carpetas

Eliminar una carpeta de una biblioteca de documentos

Para eliminar una carpeta, llame a la función deleteObject() en el objeto. El ejemplo siguiente usa el método getFolderByServerRelativeUrl para recuperar la carpeta de la biblioteca de documentos y luego elimina el elemento.

function deleteFolder(resultpanel) {
    var clientContext;
    var oWebsite;
    var folderUrl;

    clientContext = new SP.ClientContext.get_current();
    oWebsite = clientContext.get_web();

    clientContext.load(oWebsite);
    clientContext.executeQueryAsync(function () {
        folderUrl = oWebsite.get_serverRelativeUrl() + 
                             "/Lists/Shared Documents/Folder1";
        this.folderToDelete = oWebsite.getFolderByServerRelativeUrl(folderUrl);
        this.folderToDelete.deleteObject();

        clientContext.executeQueryAsync(
            Function.createDelegate(this, successHandler),
            Function.createDelegate(this, errorHandler)
        );
    }, errorHandler);

    function successHandler() {
        resultpanel.innerHTML = "Go to the " +
            "<a href='../Lists/Shared Documents'>document library</a> " +
            "to make sure the folder is no longer there.";
    }

    function errorHandler() {
        resultpanel.innerHTML = "Request failed: " + arguments[1].get_message();
    }
}

5.2.5.2 - Crear, actualizar y eliminar carpetas

Actualizar una carpeta en una biblioteca de documentos

Para actualizar el nombre de una carpeta, se puede escribir en la propiedad FileLeafRef y llamar a la función update() para que los cambios surtan efecto cuando llame al método executeQueryAsync.

function updateFolder(resultpanel) {
    var clientContext;
    var oWebsite;
    var oList;

    clientContext = new SP.ClientContext.get_current();
    oWebsite = clientContext.get_web();
    oList = oWebsite.get_lists().getByTitle("Shared Documents");

    this.oListItem = oList.getItemById(1);
    this.oListItem.set_item("FileLeafRef", "My updated folder");
    this.oListItem.update();

    clientContext.load(this.oListItem);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, successHandler),
        Function.createDelegate(this, errorHandler)
    );

    function successHandler() {
        resultpanel.innerHTML = "Go to the " +
            "<a href='../Lists/Shared Documents'>document library</a> " +
            "to see your updated folder.";
    }

    function errorHandler() {
        resultpanel.innerHTML = "Request failed: " + arguments[1].get_message();
    }
}

5.2.5.1 - Crear, actualizar y eliminar carpetas

Crear, actualizar y eliminar carpetas

Se pueden manipular carpetas para organizar el contenido usando el modelo de objetos JavaScript.

Crear una carpeta en una biblioteca de documentos

Para crear una carpeta, se debe usar un objeto ListItemCreationInformation, se debe establecer el tipo de objeto subyacente en SP.FileSystemObjectType.folder y pasarlo como parámetro a la función addItem(parameters) del objeto List.
Luego se deben establecer las propiedades en el objeto de elemento de lista que este método devuelve y luego llame a la función update(), como se ve en el ejemplo siguiente.

function createFolder(resultpanel) {
    var clientContext;
    var oWebsite;
    var oList;
    var itemCreateInfo;

    clientContext = new SP.ClientContext.get_current();
    oWebsite = clientContext.get_web();
    oList = oWebsite.get_lists().getByTitle("Shared Documents");

    itemCreateInfo = new SP.ListItemCreationInformation();
    itemCreateInfo.set_underlyingObjectType(SP.FileSystemObjectType.folder);
    itemCreateInfo.set_leafName("My new folder!");
    this.oListItem = oList.addItem(itemCreateInfo);
    this.oListItem.update();

    clientContext.load(this.oListItem);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, successHandler),
        Function.createDelegate(this, errorHandler)
    );

    function successHandler() {
        resultpanel.innerHTML = "Go to the " +
            "<a href='../Lists/Shared Documents'>document library</a> " +
            "to see your new folder.";
    }

    function errorHandler() {
        resultpanel.innerHTML =
            "Request failed: " + arguments[1].get_message();
    }
}

5.2.4.3 - Crear, actualizar y eliminar listas

Eliminar una lista

Para eliminar una lista, llame a la función deleteObject() del objeto List, como se muestra en el siguiente ejemplo.

function deleteList(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oWebsite = clientContext.get_web();
    this.listTitle = 'My Announcements List';

    this.oList = oWebsite.get_lists().getByTitle(listTitle);
    oList.deleteObject();

    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded() {
    var result = listTitle + ' deleted.';
    alert(result);
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

5.2.4.2 - Crear, actualizar y eliminar listas

Agregar un campo a una lista

Use add(field) o la función addFieldAsXml(schemaXml, addToDefaultView, options) del objeto FieldCollection para agregar un campo a la colección de campos de una lista. En el siguiente ejemplo se crea un campo y, posteriormente, se actualiza antes de llamar a executeQueryAsync(succeededCallback, failedCallback).

function addFieldToList(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);

    var oList = clientContext.get_web().get_lists().getByTitle('Announcements');
    
    this.oField = oList.get_fields().addFieldAsXml(
        '<Field DisplayName=\'MyField\' Type=\'Number\' />', 
        true, 
        SP.AddFieldOptions.defaultValue
    );

    var fieldNumber = clientContext.castTo(oField,SP.FieldNumber);
    fieldNumber.set_maximumValue(100);
    fieldNumber.set_minimumValue(35);
    fieldNumber.update();

    clientContext.load(oField);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded() {
    var result = oField.get_title() + ' added.';
    alert(result);
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

5.2.4.1 - Crear, actualizar y eliminar listas

Crear, actualizar y eliminar listas

La creación, la actualización y la eliminación de listas por medio del modelo de objetos de cliente funcionan de manera similar al modo en que se llevan a cabo estas tareas mediante el modelo de objetos de cliente .NET. No obstante, las operaciones de cliente no se completarán hasta que se llame a la función executeQueryAsync(succeededCallback, failedCallback).

Crear y actualizar una lista

Parar crear un objeto List con JavaScript, use el objeto ListCreationInformation para definir sus propiedades y luego pase este objeto a la función add(parameters) del objeto ListCollection.
 En el siguiente ejemplo se crea una lista de anuncios.

function createList(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oWebsite = clientContext.get_web();
    
    var listCreationInfo = new SP.ListCreationInformation();
    listCreationInfo.set_title('My Announcements List');
    listCreationInfo.set_templateType(SP.ListTemplateType.announcements);

    this.oList = oWebsite.get_lists().add(listCreationInfo);

    clientContext.load(oList);
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded() {
    var result = oList.get_title() + ' created.';
    alert(result);
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

Si se necesita actualizar la lista una vez creada, se pueden establecer las propiedades de la lista y llamar a la función update() antes de llamar a executeQueryAsync(succeededCallback, failedCallback) como se muestra en las siguientes modificaciones del ejemplo anterior

.
.
.
.
this.oList = oWebsite.get_lists().add(listCreationInfo);

oList.set_description('New Announcements List');
oList.update();

clientContext.load(oList);
clientContext.executeQueryAsync(
    Function.createDelegate(this, this.onQuerySucceeded), 
    Function.createDelegate(this, this.onQueryFailed)
);

5.2.3.2 - Tareas de lista de SharePoint #2

Almacenar listas devueltas en una colección

Como se ve en el ejemplo siguiente, se puede usar el método loadQuery(clientObjectCollection, exp) en lugar del método load(clientObject) para almacenar el valor devuelto en otra colección en lugar de almacenarlo en la propiedad de las listas.

function retrieveSpecificListPropertiesToCollection(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oWebsite = clientContext.get_web();
    var collList = oWebsite.get_lists();

    this.listInfoCollection = 
         clientContext.loadQuery(collList, 'Include(Title, Id)');
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded() {
    var listInfo = '';

    for (var i = 0; i < this.listInfoCollection.length; i++) {
        var oList = this.listInfoCollection[i];
        listInfo += 'Title: ' + oList.get_title() + 
            ' ID: ' + oList.get_id().toString();
    }
    alert(listInfo.toString());
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

Aplicar filtros a la recuperación de listas

Como se muestra en el ejemplo siguiente, puede anidar instrucciones Include en una consulta JavaScript, para devolver metadatos de listas y campos. En el ejemplo se devuelven todos los campos de todas las listas dentro de un sitio web, y se muestra el título y el nombre interno de todos los campos cuyo nombre interno contiene la cadena "name".

function retrieveAllListsAllFields(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oWebsite = clientContext.get_web();
    var collList = oWebsite.get_lists();

    this.listInfoArray = clientContext.loadQuery(collList, 
        'Include(Title,Fields.Include(Title,InternalName))');

    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this._onQueryFailed)
    );
}

function onQuerySucceeded() {
    var listInfo = '';

    for (var i = 0; i < this.listInfoArray.length; i++) {
        var oList = this.listInfoArray[i];
        var collField = oList.get_fields();
        var fieldEnumerator = collField.getEnumerator();
            
        while (fieldEnumerator.moveNext()) {
            var oField = fieldEnumerator.get_current();
            var regEx = new RegExp('name', 'ig');
            
            if (regEx.test(oField.get_internalName())) {
                listInfo += '\nList: ' + oList.get_title() + 
                    '\n\tField Title: ' + oField.get_title() + 
                    '\n\tField Name: ' + oField.get_internalName();
            }
        }
    }
    alert(listInfo);
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

5.2.3.1 - Tareas de lista de SharePoint #1

Tareas de lista de SharePoint

Trabajar con objetos de lista con JavaScript es parecido a trabajar con objetos de sitio web. Se empieza por usar el constructor ClientContext(serverRelativeUrl) y pasar una dirección URL o URI para devolver un contexto de consulta específico. Después se puede usar la propiedad lists de la clase Web para obtener la colección de listas del sitio web.

Recuperar todas las propiedades de todas las listas de un sitio web

Para devolver todas las listas de un sitio web, se carga la colección de listas con el método load(clientObject) y luego se llama a executeQueryAsync(succeededCallback, failedCallback).
En el siguiente ejemplo se muestra la dirección URL del sitio web, y la fecha y hora, en que se creó la lista.
function retrieveAllListProperties(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oWebsite = clientContext.get_web();
    this.collList = oWebsite.get_lists();
    clientContext.load(collList);

    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded() {
    var listInfo = '';
    var listEnumerator = collList.getEnumerator();

    while (listEnumerator.moveNext()) {
        var oList = listEnumerator.get_current();
        listInfo += 'Title: ' + oList.get_title() + ' Created: ' + 
            oList.get_created().toString() + '\n';
    }
    alert(listInfo);
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

Recuperar solo propiedades específicas de listas

En el ejemplo anterior se devuelven todas las propiedades de las listas de un sitio web. Para reducir la transferencia de datos innecesarios entre cliente y servidor, se puede usar expresiones de consultas LINQ para especificar qué propiedades devolver. En JavaScript, se especifica Include como parte de la cadena de la consulta que se pasa al método load(clientObject) para especificar qué propiedades devolver. 
En el siguiente ejemplo se usa este enfoque para devolver solo el título y el identificador de cada una de las listas de la colección.

function retrieveSpecificListProperties(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    var oWebsite = clientContext.get_web();
    this.collList = oWebsite.get_lists();

    clientContext.load(collList, 'Include(Title, Id)');
    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded() {
    var listInfo = '';
    var listEnumerator = collList.getEnumerator();

    while (listEnumerator.moveNext()) {
        var oList = listEnumerator.get_current();
        listInfo += 'Title: ' + oList.get_title() + 
            ' ID: ' + oList.get_id().toString() + '\n';
    }
    alert(listInfo);
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

5.2.2 - Tareas a nivel sitio web de SharePoint

Tareas de sitio web de SharePoint

Para trabajar con sitios web con JavaScript, se debe comenzar utilizando el constructor ClientContext(serverRelativeUrl) y pasarle la dirección URL o URI para que devuelva un contexto de solicitud específico el sitio web.

Recuperar las propiedades de un sitio web

Use la propiedad web de la clase ClientContext para especificar las propiedades del objeto de sitio web que se encuentra en la dirección URL del contexto especificado. Después de cargar el objeto de sitio web con el método load(clientObject) y, posteriormente, llamar a executeQueryAsync(succeededCallback, failedCallback), se obtendrá acceso a todas las propiedades de ese sitio web.
A continuación se muestra el título y la descripción del sitio web especificado, aunque el resto de las propiedades devueltas de forma predeterminada se ponen a disposición después de cargar el objeto de sitio web y ejecutar la consulta.


function retrieveWebSite(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    this.oWebsite = clientContext.get_web();

    clientContext.load(this.oWebsite);

    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded(sender, args) {
    alert('Title: ' + this.oWebsite.get_title() + 
        ' Description: ' + this.oWebsite.get_description());
}
    
function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

Recuperar solo las propiedades seleccionadas de un sitio web

Para reducir la transferencia de datos innecesaria entre cliente y servidor, es posible devolver solo las propiedades especificadas del objeto de sitio web, en lugar de todas sus propiedades. En este caso, se usa la sintaxis de la expresión lambda o consulta LINQ con el método load(clientObject) para especificar las propiedades que se van a devolver desde el servidor. 
A continuación, solo se ponen a disposición el título y la fecha de creación del objeto de sitio web después de llamar a executeQueryAsync(succeededCallback, failedCallback).

function retrieveWebSiteProperties(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    this.oWebsite = clientContext.get_web();

    clientContext.load(this.oWebsite, 'Title', 'Created');

    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded(sender, args) {
    alert('Title: ' + this.oWebsite.get_title() + 
        ' Created: ' + this.oWebsite.get_created());
}
    
function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

Escribir en las propiedades de un sitio web

Para modificar un sitio web, se deben establecer las propiedades y llamar al método update(), de manera similar al modo en que funciona el modelo de objetos de servidor. Sin embargo, en el modelo de objetos de cliente, debe llamar a executeQueryAsync(succeededCallback, failedCallback) para solicitar el procesamiento por lotes para todos los comandos que se especifiquen.
A continuación se cambia el título y la descripción de un sitio web especificado.

function updateWebSite(siteUrl) {
    var clientContext = new SP.ClientContext(siteUrl);
    this.oWebsite = clientContext.get_web();

    this.oWebsite.set_title('Updated Web Site');
    this.oWebsite.set_description('This is an updated Web site.');
    this.oWebsite.update();

    clientContext.load(this.oWebsite, 'Title', 'Description');

    clientContext.executeQueryAsync(
        Function.createDelegate(this, this.onQuerySucceeded), 
        Function.createDelegate(this, this.onQueryFailed)
    );
}

function onQuerySucceeded(sender, args) {
    alert('Title: ' + this.oWebsite.get_title() + 
        ' Description: ' + this.oWebsite.get_description());
}
    
function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + 
        '\n' + args.get_stackTrace());
}

5.2.1 - Procedimiento para realizar operaciones básicas con código de biblioteca de JavaScript en SharePoint 2013

Ejecutar tareas básicas en SharePoint 2013 con el modelo de objetos de cliente JavaScript

Al crear una aplicación auto-hosted en la nube, se puede agregar una referencia al modelo de objetos dentro de las etiquetas <script> de HTML.
Se recomienda hacer referencia a la web donde se hostea la aplicación para garantizar la existencia del contexto en las aplicaciones auto-hosted.
Para recuperar la dirección URL a la web donde se hostea la aplicación, puede hacerse obteniendo el parámetro SPHostUrl de los parámetros de la consulta.
Una vez obtenida la dirección URL de la web donde se hostea la aplicación, se puede utilizar código JavaScript para crear dinámicamente la referencia al modelo de objetos.

En el ejemplo siguiente se ejecutan estas tareas para referenciar al modelo de objetos JavaScript:
  1. Hace referencia a la biblioteca AJAX desde la Microsoft Content Delivery Network (CDN)
  2. Hace referencia a la biblioteca jQuery desde la CDN de Microsoft.
  3. Extrae la dirección URL a la web donde se hostea la aplicación desde los parámetros de la  consulta. (http://www.w3schools.com/jsref/jsref_decodeuricomponent.asp)
  4. Cargar los archivos SP.Runtime.js y SP.js a través de la función getScript de jQuery. Luego de cargar los archivos js, el programa obtendrá acceso al modelo de objetos JavaScript de SharePoint. (http://www.w3schools.com/jquery/ajax_getscript.asp )
  5. La aplicación continúa en la función execOperation.


<script 
    src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js" 
    type="text/javascript">
</script>
<script
    type="text/javascript"
    src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js">
</script>
<script type="text/javascript">
    var hostweburl;

    // Load the required SharePoint libraries.
    $(document).ready(function () {

        // Get the URI decoded URLs.
        hostweburl =
            decodeURIComponent(
                getQueryStringParameter("SPHostUrl")
        );

        // The js files are in a URL in the form:
        // web_url/_layouts/15/resource_file
        var scriptbase = hostweburl + "/_layouts/15/";

        // Load the js files and continue to
        // the execOperation function.
        $.getScript(scriptbase + "SP.Runtime.js",
            function () {
                $.getScript(scriptbase + "SP.js", execOperation);
            }
        );
    });

    // Function to execute basic operations.
    function execOperation() {

        // Continue your program flow here.

    }

    // Function to retrieve a query string value.
    // For production purposes you may want to use
    // a library to handle the query string.
    function getQueryStringParameter(paramToRetrieve) {
        var params = document.URL.split("?")[1].split("&");
        var strParams = "";
        for (var i = 0; i < params.length; i = i + 1) {
            var singleParam = params[i].split("=");
            if (singleParam[0] == paramToRetrieve)
                return singleParam[1];
        }
    }
</script>

Una alternativa para obtener las referencias al modelo de objetos dentro de las etiquetas <script> de HTML es a través de la propia web de aplicación auto-hosted en SharePoint que permite usar rutas de acceso relativas para hacer referencia a los archivos necesarios para usar el modelo de objetos JavaScript

En el siguiente ejemplo se ejecutan las siguientes tareas para agregar una referencia al modelo de objetos JavaScript utilizando esta técnica:
  1. Hacer referencia a la biblioteca AJAX desde la CDN de Microsoft.
  2. Hacer referencia al archivo SP.Runtime.js con una dirección URL relativa a la web de aplicación.
  3. Hace referencia al archivo SP.js con una dirección URL relativa a la web de aplicación.
<script 
    src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js" 
    type="text/javascript">
</script>
<script 
    type="text/javascript" 
    src="/_layouts/15/sp.runtime.js">
</script>
<script 
    type="text/javascript" 
    src="/_layouts/15/sp.js">
</script>
<script type="text/javascript">

    // Continue your program flow here.

</script>

5.1 - Resumen de lo Visto

Temas tratados

  • Arquitecturas de SharePoint 2013
    • SharePoint Online
    • SharePoint OnPremise
  • Técnicas Desarrollo en SharePoint 2013
    • Soluciones Full-Trust (solo disponible para OnPremise)
    • Soluciones Parcial-Trust (Sandboxed Solutions)
    • Apps
      • Auto-Hosted App
      • Provisioned-Hosted App
        • Provider
        • Azure
  • Desarrollo de Apps
    • Independencia de la tecnología
    • Uso de JavaScript, CSOM, .Net Managed
    • Nueva api disponible a través de _api (en reemplazo de _vti_bin/server.svc)
  • Office 365: Usuario y entorno para desarrollo
  • Arquiteturas de Azure (IaaS, PaaS, SaaS)
  • Uso de JavaScript, sintaxis y estructuras
  • DOM HTML
  • Primer ejemplo de aplicación Auto-Hosted


jueves, 11 de septiembre de 2014

3.2.10 - Funciones

Funciones

Cuando se desarrolla una aplicación compleja, es muy habitual utilizar una y otra vez las mismas instrucciones. Un script para una tienda de comercio electrónico por ejemplo, tiene que calcular el precio total de los productos varias veces, para añadir los impuestos y los gastos de envío.
Cuando una serie de instrucciones se repiten una y otra vez, se complica demasiado el código fuente de la aplicación, ya que:
  • El código de la aplicación es mucho más largo porque muchas instrucciones están repetidas.
  • Si se quiere modificar alguna de las instrucciones repetidas, se deben hacer tantas modificaciones como veces se haya escrito esa instrucción, lo que se convierte en un trabajo muy pesado y muy propenso a cometer errores.
Las funciones son la solución a todos estos problemas, tanto en JavaScript como en el resto de lenguajes de programación. Una función es un conjunto de instrucciones que se agrupan para realizar una tarea concreta y que se pueden reutilizar fácilmente.
En el siguiente ejemplo, las instrucciones que suman los dos números y muestran un mensaje con el resultado se repiten una y otra vez:
var resultado;
 
var numero1 = 3;
var numero2 = 5;
 
// Se suman los números y se muestra el resultado
resultado = numero1 + numero2;
alert("El resultado es " + resultado);
 
numero1 = 10;
numero2 = 7;
 
// Se suman los números y se muestra el resultado
resultado = numero1 + numero2;
alert("El resultado es " + resultado);
 
numero1 = 5;
numero2 = 8;
 
// Se suman los números y se muestra el resultado
resultado = numero1 + numero2;
alert("El resultado es " + resultado);
...
Aunque es un ejemplo muy sencillo, parece evidente que repetir las mismas instrucciones a lo largo de todo el código no es algo recomendable. La solución que proponen las funciones consiste en extraer las instrucciones que se repiten y sustituirlas por una instrucción del tipo "en este punto, se ejecutan las instrucciones que se han extraído":
var resultado;
 
var numero1 = 3;
var numero2 = 5;
 
/* En este punto, se llama a la función que suma
    2 números y muestra el resultado */
 
numero1 = 10;
numero2 = 7;
 
/* En este punto, se llama a la función que suma
    2 números y muestra el resultado */
 
numero1 = 5;
numero2 = 8;
 
/* En este punto, se llama a la función que suma
    2 números y muestra el resultado */
...
Para que la solución del ejemplo anterior sea válida, las instrucciones comunes se tienen que agrupar en una función a la que se le puedan indicar los números que debe sumar antes de mostrar el mensaje.
Por lo tanto, en primer lugar se debe crear la función básica con las instrucciones comunes. Las funciones en JavaScript se definen mediante la palabra reservada function, seguida del nombre de la función. Su definición formal es la siguiente:
function nombre_funcion() {
  ...
}
El nombre de la función se utiliza para llamar a esa función cuando sea necesario. El concepto es el mismo que con las variables, a las que se les asigna un nombre único para poder utilizarlas dentro del código. Después del nombre de la función, se incluyen dos paréntesis cuyo significado se detalla más adelante. Por último, los símbolos { y } se utilizan para encerrar todas las instrucciones que pertenecen a la función (de forma similar a como se encierran las instrucciones en las estructuras if o for).
Volviendo al ejemplo anterior, se crea una función llamada suma_y_muestra de la siguiente forma:
function suma_y_muestra() {
  resultado = numero1 + numero2;
  alert("El resultado es " + resultado);
}
Aunque la función anterior está correctamente creada, no funciona como debería ya que le faltan los"argumentos". Una vez creada la función, desde cualquier punto del código se puede llamar a la función para que se ejecuten sus instrucciones (además de "llamar a la función", también se suele utilizar la expresión "invocar a la función").
La llamada a la función se realiza simplemente indicando su nombre, incluyendo los paréntesis del final y el carácter ; para terminar la instrucción:
function suma_y_muestra() {
  resultado = numero1 + numero2;
  alert("El resultado es " + resultado);
}
 
var resultado;
 
var numero1 = 3;
var numero2 = 5;
 
suma_y_muestra();
 
numero1 = 10;
numero2 = 7;
 
suma_y_muestra();
 
numero1 = 5;
numero2 = 8;
 
suma_y_muestra();
...
El código del ejemplo anterior es mucho más eficiente que el primer código que se mostró, ya que no existen instrucciones repetidas. Las instrucciones que suman y muestran mensajes se han agrupado bajo una función, lo que permite ejecutarlas en cualquier punto del programa simplemente indicando el nombre de la función.
Lo único que le falta al ejemplo anterior para funcionar correctamente es poder indicar a la función los números que debe sumar. Cuando se necesitan pasar datos a una función, se utilizan los "argumentos", como se explica en la siguiente sección.

Argumentos y valores de retorno

Las funciones más sencillas no necesitan ninguna información para producir sus resultados. Sin embargo, la mayoría de funciones de las aplicaciones reales deben acceder al valor de algunas variables para producir sus resultados.
Las variables que necesitan las funciones se llaman argumentos. Antes de que pueda utilizarlos, la función debe indicar cuántos argumentos necesita y cuál es el nombre de cada argumento. Además, al invocar la función, se deben incluir los valores que se le van a pasar a la función. Los argumentos se indican dentro de los paréntesis que van detrás del nombre de la función y se separan con una coma (,).
Siguiendo el ejemplo anterior, la función debe indicar que necesita dos argumentos, correspondientes a los dos números que tiene que sumar:
function suma_y_muestra(primerNumero, segundoNumero) { ... }
A continuación, para utilizar el valor de los argumentos dentro de la función, se debe emplear el mismo nombre con el que se definieron los argumentos:
function suma_y_muestra(primerNumero, segundoNumero) { ... }
  var resultado = primerNumero + segundoNumero;
  alert("El resultado es " + resultado);
}
Dentro de la función, el valor de la variable primerNumero será igual al primer valor que se le pase a la función y el valor de la variable segundoNumero será igual al segundo valor que se le pasa. Para pasar valores a la función, se incluyen dentro de los paréntesis utilizados al llamar a la función:
// Definición de la función
function suma_y_muestra(primerNumero, segundoNumero) { ... }
  var resultado = primerNumero + segundoNumero;
  alert("El resultado es " + resultado);
}
 
// Declaración de las variables
var numero1 = 3;
var numero2 = 5;
 
// Llamada a la función
suma_y_muestra(numero1, numero2);
En el código anterior, se debe tener en cuenta que:
  • Aunque casi siempre se utilizan variables para pasar los datos a la función, se podría haber utilizado directamente el valor de esas variables: suma_y_muestra(3, 5);
  • El número de argumentos que se pasa a una función debería ser el mismo que el número de argumentos que ha indicado la función. No obstante, JavaScript no muestra ningún error si se pasan más o menos argumentos de los necesarios.
  • El orden de los argumentos es fundamental, ya que el primer dato que se indica en la llamada, será el primer valor que espera la función; el segundo valor indicado en la llamada, es el segundo valor que espera la función y así sucesivamente.
  • Se puede utilizar un número ilimitado de argumentos, aunque si su número es muy grande, se complica en exceso la llamada a la función.
  • No es obligatorio que coincida el nombre de los argumentos que utiliza la función y el nombre de los argumentos que se le pasan. En el ejemplo anterior, los argumentos que se pasan son numero1 ynumero2 y los argumentos que utiliza la función son primerNumero y segundoNumero.
A continuación se muestra otro ejemplo de una función que calcula el precio total de un producto a partir de su precio básico:
// Definición de la función
function calculaPrecioTotal(precio) {
  var impuestos = 1.16;
  var gastosEnvio = 10;
  var precioTotal = ( precio * impuestos ) + gastosEnvio;
}
 
// Llamada a la función
calculaPrecioTotal(23.34);
La función anterior toma como argumento una variable llamada precio y le suma los impuestos y los gastos de envío para obtener el precio total. Al llamar a la función, se pasa directamente el valor del precio básico mediante el número 23.34.
No obstante, el código anterior no es demasiado útil, ya que lo ideal sería que la función pudiera devolver el resultado obtenido para guardarlo en otra variable y poder seguir trabajando con este precio total:
function calculaPrecioTotal(precio) {
  var impuestos = 1.16;
  var gastosEnvio = 10;
  var precioTotal = ( precio * impuestos ) + gastosEnvio;
}
 
// El valor devuelto por la función, se guarda en una variable
var precioTotal = calculaPrecioTotal(23.34);
 
// Seguir trabajando con la variable "precioTotal"
Afortunadamente, las funciones no solamente puede recibir variables y datos, sino que también pueden devolver los valores que han calculado. Para devolver valores dentro de una función, se utiliza la palabra reservada return. Aunque las funciones pueden devolver valores de cualquier tipo, solamente pueden devolver un valor cada vez que se ejecutan.
function calculaPrecioTotal(precio) {
  var impuestos = 1.16;
  var gastosEnvio = 10;
  var precioTotal = ( precio * impuestos ) + gastosEnvio;
  return precioTotal;
}
 
var precioTotal = calculaPrecioTotal(23.34);
 
// Seguir trabajando con la variable "precioTotal"
Para que la función devuelva un valor, solamente es necesario escribir la palabra reservada return junto con el nombre de la variable que se quiere devolver. En el ejemplo anterior, la ejecución de la función llega a la instrucción return precioTotal; y en ese momento, devuelve el valor que contenga la variableprecioTotal.
Como la función devuelve un valor, en el punto en el que se realiza la llamada, debe indicarse el nombre de una variable en el que se guarda el valor devuelto:
var precioTotal = calculaPrecioTotal(23.34);
Si no se indica el nombre de ninguna variable, JavaScript no muestra ningún error y el valor devuelto por la función simplemente se pierde y por tanto, no se utilizará en el resto del programa. En este caso, tampoco es obligatorio que el nombre de la variable devuelta por la función coincida con el nombre de la variable en la que se va a almacenar ese valor.
Si la función llega a una instrucción de tipo return, se devuelve el valor indicado y finaliza la ejecución de la función. Por tanto, todas las instrucciones que se incluyen después de un return se ignoran y por ese motivo la instrucción return suele ser la última de la mayoría de funciones.
Para que el ejemplo anterior sea más completo, se puede añadir otro argumento a la función que indique el porcentaje de impuestos que se debe añadir al precio del producto. Evidentemente, el nuevo argumento se debe añadir tanto a la definición de la función como a su llamada:
function calculaPrecioTotal(precio, porcentajeImpuestos) {
  var gastosEnvio = 10;
  var precioConImpuestos = (1 + porcentajeImpuestos/100) * precio;
  var precioTotal = precioConImpuestos + gastosEnvio;
  return precioTotal;
}
 
var precioTotal = calculaPrecioTotal(23.34, 16);
var otroPrecioTotal = calculaPrecioTotal(15.20, 4);
Para terminar de completar el ejercicio anterior, se puede rendondear a dos decimales el precio total devuelto por la función:
function calculaPrecioTotal(precio, porcentajeImpuestos) {
  var gastosEnvio = 10;
  var precioConImpuestos = (1 + porcentajeImpuestos/100) * precio;
  var precioTotal = precioConImpuestos + gastosEnvio;
  return precioTotal.toFixed(2);
}
 
var precioTotal = calculaPrecioTotal(23.34, 16);