Oracle CRM On Demand Desktop Administration Guide > Code Listing for Updates to the Customization Package from Version 2.0 >

JavaScript Code Addition for the od_helpers.js File


Insert the following JavaScript code after the first line of the file, as described in Step 8:

include("form_helpers.js", "form_helpers");

var allow_includesubbooks =
{
//   "Account": true
};

function book_selector(ctx, options)
{
   var session = ctx.session,
      ui = ctx.ui,
      dlg,
      tree,
      image = "",
      on_changed;
      
   var btn = options.ctrl_btn,
      edit = options.ctrl_edit,
      id_field = options.field || "BookId",
      ownership_mode = options.mode,
      context = options.context,
      in_tree = {};
   
   edit.enabled = false;
   on_changed = new helpers.signal();
   this.on_changed = on_changed;
   this.refresh = refresh;
   if(context == "inspector")
   {
      ctx.events.connect(btn, "on_click", show);
      dlg = ctx.ui.create_dialog(0, "select_book_dialog");
      tree = dlg.books_tree;
      ctx.events.connect(tree, "on_node_activated", select);
      ctx.events.connect(dlg.btn_cancel, "on_click", on_cancel);
      ctx.events.connect(dlg.btn_ok, "on_click", on_save);
      ctx.events.connect(dlg.btn_clear, "on_click", on_clear);
      dlg.btn_clear.visible = true;
      btn.enabled = ownership_mode != "owner";
      this.refresh();
   }
      
   this.set_visible = function(visible)
   {
      edit.visible = btn.visible = visible;
   }
   
   function fill_tree(parent_book_id, parent_node, seelected_book_id)
   {
      parent_book_id = parent_book_id || "";
      parent_node = parent_node || tree;
      var add_node = function(item)
      {
         var book_id = item.Value
            book_name = item.Label;
         image = "book_" + (item.CanContainDataFlag ? "can" : "cannot") + "_contain_data_icon";
         var node = parent_node.nodes.add(book_name, image, {"id": book_id});
         if(book_id == seelected_book_id && book_id)
            tree.selected = node;
         in_tree[book_id] = true;
         fill_tree(book_id, node, seelected_book_id);
      }
      for_each_child(parent_book_id, add_node);
      // handle orphans
      if(parent_book_id == "")   // top level
      {

         helpers.for_each(session.find_items("Book", session.empty_criteria), function(item)
         {
            var has_no_parent = session.find_item("Book", session.create_expression("Value", "eq", item.ParentBookId)) == null;
            if(!in_tree[item.Value] && has_no_parent)
               add_node(item);
         });
      }
   };

   function show()
   {
      dlg.visible = true;
      tree.nodes.remove_all();
      in_tree = {};
      fill_tree(null, null, ctx.item_ex.get_property(id_field));
      // Tree refresh workaround
      dlg.btn_clear.set_focus();
      tree.set_focus();
   }
   
   function refresh()
   {
      edit.value = id_to_label(ctx.item_ex.get_property(id_field));
   }
   
   function on_cancel(){dlg.close();}
   
   function on_save(){
      var selected_node = tree.selected;
      select(selected_node);   
   }
   
   function on_clear(){
      tree.selected = null;
   }
   
   function select(node)
   {
      edit.value = node != null ? node.name : "";
      var book_id = node != null ? node.data.id : "";
      ctx.item_ex.set_property(id_field, book_id);
      dlg.close();
      on_changed.raise(book_id);
   }
   
   function for_each_child(parent_book_id, fn)
   {
      helpers.for_each(session.find_items("Book", session.create_expression("ParentBookId", "eq", parent_book_id)), fn);
   }
   
   function id_to_label(id)
   {
      var book = id != null ? session.find_item("Book", session.create_expression("Value", "eq", id)) : null;
      var label = "";
      if(book != null)
         label = book.Label;
      else
         if(id != null && id != "")
         {
            var user = ctx.session.find_item("User", ctx.session.create_expression("PrimaryPositionId", "eq", id));
            if(user != null)
               label = user["FullName"];
            else
               label = session.res_string("inaccessible_book");
         }
      return label;
   }

   function get_current_user_userbook(ctx)
   {
      var defaults = helpers.get_defaults(ctx.session);
      return defaults != null ? defaults.PrimaryPositionId : "";
   }
}

function book_can_contain_data(ctx, id)
{
   var book = ctx.session.find_item("Book", ctx.session.create_expression("Value", "eq", id)),
      result = true;
   if(book != null)
      result = book.CanContainDataFlag;
   return result;
}

function book_is_userbook(ctx, id)
{
   var user = ctx.session.find_item("User", ctx.session.create_expression("PrimaryPositionId", "eq", id));
   return user != null;
}

function get_ownership_mode(ctx, type)
{
   if(type == "Event" || type == "Task" || type == "Mail")
      type = "Activity";
   var mode = "owner";
   var books_enabled = ctx.session.find_item("Book", ctx.session.create_criteria("or")) != null;
   if(books_enabled)
   {
      var owner_filter = ctx.session.create_criteria("and");
      owner_filter.add(ctx.session.create_expression("TypeName", "eq", type));
      owner_filter.add(ctx.session.create_expression("Required", "eq", true));
      owner_filter.add(ctx.session.create_expression("Value", "eq", "Owner"));
      var owner_required = ctx.session.find_item("RequiredFields", owner_filter) != null;
      if(!owner_required)
      {
         var book_filter = ctx.session.create_criteria("and");
         book_filter.add(ctx.session.create_expression("TypeName", "eq", type));
         book_filter.add(ctx.session.create_expression("Value", "eq", "BookName"));
         var oField = ctx.session.find_item("RequiredFields", book_filter);
         var book_required = oField != null ? oField.Required : null;
         if (book_required)
            mode = "book";
         else
            mode = "mixed";
      }
   }
   return mode;
}

function cp_book_selector(ctx, options)
{
   var dlg;
   var tree;
   var image = "";
   var btn = options.ctrl_btn;
   var edit = options.ctrl_edit;
   var books = options.books;
   var allow_include_subbooks = options.allow_include_subbooks;
   var selected_book;
   var on_changed = new helpers.signal();
   this.on_changed = on_changed;
   
   edit.enabled = false;
   ctx.events.connect(btn, "on_click", show);
   dlg = ctx.ui.create_dialog(0, "select_book_dialog");
   dlg.include_subitems.visible = true;
   dlg.include_subitems.enabled = allow_include_subbooks;
   tree = dlg.books_tree;
   ctx.events.connect(tree, "on_node_activated", select);
   ctx.events.connect(tree, "on_node_selected", uncheck_include_subitems);
   ctx.events.connect(dlg.btn_cancel, "on_click", on_cancel);
   ctx.events.connect(dlg.btn_ok, "on_click", on_save);
      
   this.set_visible = function(visible) {
      edit.visible = btn.visible = visible;
   };
   
   this.enable = function(enabled) {
      btn.enabled = enabled;
   }
   
   this.update_options = function (new_options) {
      btn = new_options.ctrl_btn || btn;
      edit = new_options.ctrl_edit || edit;
      books = new_options.books || books;
   };

   function show() {
      dlg.visible = true;
      tree.nodes.remove_all();
      fill_tree();
      // Tree refresh workaround
      dlg.include_subitems.set_focus();
      tree.set_focus();
   }
   
   function on_cancel() { dlg.close(); }
   
   function on_save() {
      select(tree.selected);   
   }
   
   function select(node) {
      var selected_book_id = node != null ? node.data.id : null;
      var selected_include_subitems = node != null ? dlg.include_subitems.checked : null;
      if (selected_book_id) {
         if (selected_include_subitems || books[selected_book_id].CanContainDataFlag) {
            set_book_selected({BookId: selected_book_id, IncludeSubBooks: selected_include_subitems});
            uncheck_include_subitems();
            dlg.close();
         } else {
            var message = (allow_include_subbooks ? "msg_subitems_required_for_book" : "msg_cannot_select_book_subitems_disallowed");
            ctx.ui.message_box(0, ctx.session.res_string(message), ctx.session.res_string("msg_validation_failed"), 0x30);
         }
      } else {
         dlg.close();
      }
   }
   
   var set_book_selected = function (book) {
      selected_book = book;
      refresh(book);
      on_changed.raise(book);
   }
   this.set_book_selected = set_book_selected;
   
   function uncheck_include_subitems() { dlg.include_subitems.checked = false; }
   
   function fill_tree(parent_book_id, parent_node) {
      parent_book_id = parent_book_id || "";
      parent_node = parent_node || tree;
      for_each_child(parent_book_id, add_node);
      // handle orphans
      if (parent_book_id == "") {
         helpers.for_each2(books, function(item) {
            var parent_inaccessible = books[item.ParentBookId] == null;
            if (item.ParentBookId != "" && parent_inaccessible)
               add_node(item);
         });
      }
      function add_node(item) {
         var book_id = item.Value,
            book_name = item.Label;
         image = "book_" + (item.CanContainDataFlag ? "can" : "cannot") + "_contain_data_icon";
         var node = parent_node.nodes.add(book_name, image, {"id": book_id});
         if(selected_book && book_id && selected_book.BookId == book_id) {
            tree.selected = node;
            dlg.include_subitems.checked = dlg.include_subitems.visible && !!selected_book.IncludeSubBooks;
         }
         fill_tree(book_id, node);
      }
      function for_each_child(parent_book_id, fn) {
         var child_books = [];
         helpers.for_each2(books, function (item) {
            if (item.ParentBookId == parent_book_id)
               child_books.push(item);
         });
         helpers.for_each2(child_books, fn);
      }
   };
   
   function refresh(book) {
      // Update book label
      var book_id = book != null ? book.BookId : null;
      var label = "";
      if (book_id != null && book_id != "")
         label = books[book_id] != null
            ? (books[book_id].Label + (book.IncludeSubBooks ? "+" : ""))
            : ctx.session.res_string("inaccessible_book");

      edit.value = label;
   }
}

function record_set_page(ctx)
{
   var parent_form, form = ctx.form;
   var cached_bs_controllers = {};
   var saved_item_snapshot, current_item;
   var record_set_types = [];
   var book_processor, predefined_options = {};
   
   ctx.events.connect(form.btn_save1, "on_click", on_save);
   ctx.events.connect(form, "on_action_requested", on_action_requested);
   
   function saved_books_retrieved(retrieved_books) {
      current_item = retrieved_books;
      rebuild_saved_item_snapshot();
      
      // Switch back to active page UI from on_busy
      switch_back_from_daisy();
      form.head_record_type.visible = form.head_visibility_model.visible = form.head_book_name.visible = true;
      
      // Get list of supported types
      record_set_types = book_processor.get_types_list();
      
      // Clear previous records set controls table
      var i = 0;
      helpers.for_each2(record_set_types, function(){
         var img_type = form["img_type" + i],
            lbl_type = form["lbl_type" + i],
            cbx_mode = form["cbx_mode" + i],
            edit_book = form["edit_book" + i],
            btn_book_select = form["btn_book_select" + i];
         
         img_type.image = null;
         lbl_type.caption = "";
         cbx_mode.value = null;
         img_type.visible = lbl_type.visible = cbx_mode.visible = edit_book.visible = btn_book_select.visible = false;
         i++;
      });
         
      build_table();
   }
   
   function build_table() {
      var row_num = 0;
      // Disable "Save" button initially
      validate_changes();
      // Build table
      helpers.for_each2(record_set_types, function(rs_type){
         var img_type = form["img_type" + row_num],
            lbl_type = form["lbl_type" + row_num],
            cbx_mode = form["cbx_mode" + row_num],
            edit_book = form["edit_book" + row_num],
            btn_book_select = form["btn_book_select" + row_num];
         var book_available = rs_type.books_enabled && book_processor.user_has_books();
         
         // Make type image, caption and mode selector visible
         var caption_lbl = rs_type.type_id;
         try { img_type.image = "type_image:"+rs_type.type_id+":24"; } catch(e){}
         try { caption_lbl = ctx.session.res_string("obj_"+rs_type.type_id.toLowerCase()); } catch(e){}
         lbl_type.caption = caption_lbl;
         img_type.visible = lbl_type.visible = cbx_mode.visible = true;
         cbx_mode.enabled = edit_book.visible = btn_book_select.visible = book_available;
         var current_type_settings;
         book_processor.apply_to_type(rs_type.type_id, function(item){current_type_settings = item}, current_item);   // set current_type_settings            

         // Build mode selector options
         cbx_mode.items.clear();
         cbx_mode.items.start_adding();
         cbx_mode.items.add("team", ctx.session.res_string("cbx_record_set_team"));
         if (book_available || current_type_settings.BookId != null)
            cbx_mode.items.add("book", ctx.session.res_string("cbx_record_set_book"));
         if (book_available && book_processor.default_book_exists(rs_type) || is_default_book_selected(current_type_settings, rs_type.default_book))
            cbx_mode.items.add("default_book", ctx.session.res_string("cbx_record_set_default_book"));
         cbx_mode.items.finish_adding();

         
         // Retrieve cached book selector (or create a new one if not found)
         var books = book_processor.get_available_books();
         var bs = cached_bs_controllers[rs_type.type_id];
         if (bs) {
            bs.update_options({type: rs_type, books: books});
         } else {
                  var bs_options =
               {
               ctrl_edit: edit_book,
               ctrl_btn: btn_book_select,
               type: rs_type,
               books: books,
               allow_include_subbooks: book_processor.allow_include_subbooks(rs_type.type_id)
            };
            bs = new cp_book_selector(ctx, bs_options);
            ctx.events.connect(bs, "on_changed", set_option_selected);
            cached_bs_controllers[rs_type.type_id] = bs;
            ctx.events.connect(cbx_mode, "changed", function(){on_mode_changed(cbx_mode.value)});
         }
         
         // Fill controls with initial values
         prefill_type(current_type_settings);

         function set_option_selected(book) {
            book_processor.apply_to_type(rs_type.type_id, function(item){
               item.BookId = book.BookId;
               item.IncludeSubBooks = book.IncludeSubBooks;
            }, current_item);
            validate_changes();
         }
         
         function on_mode_changed(mode) {
            bs.set_visible(mode !== "team");
            switch (mode) {
               case "team":
                  set_option_selected(predefined_options.team);
               break;
               case "book":
                  bs.enable(true);
                  if (book_processor.default_book_exists(rs_type))
                     bs.set_book_selected(rs_type.default_book);
                  else
                     bs.set_book_selected(predefined_options.no_book_selected);
               break;
               case "default_book":
                  bs.enable(false);
                  bs.set_book_selected(rs_type.default_book);
               break;
            }
         }
         
         /**
         Prefills mode selector and appropriate controls with passed item values.
         @param item Item of type Book.Type.Association
         @type Function
         */
         function prefill_type(item) {
            var book_id = item.BookId;
            var include_subbooks = item.IncludeSubBooks;
            var mode = "team";
            if (book_id !== predefined_options.team.BookId)
               if (is_default_book_selected(item, rs_type.default_book))
                  mode = "default_book";
               else
                  mode = "book";
            cbx_mode.value = mode;
            if(mode != "team")
               cbx_mode.enabled = true;   // user should be able to switch to "team" mode in any case
            on_mode_changed(mode);
            if (mode == "book")
               bs.set_book_selected({"BookId": book_id, "IncludeSubBooks": include_subbooks});
         }
         
         function is_default_book_selected(type_item, default_book_item) {
            return type_item.BookId == default_book_item.BookId && type_item.IncludeSubBooks == default_book_item.IncludeSubBooks
         }
         
         row_num++;
      });
   }
   
   function on_save() {
      book_processor.save(current_item, on_saved);
      function on_saved(){
         rebuild_saved_item_snapshot();
         validate_changes();
      }
   }
   function on_action_requested(ar) {
      switch (ar.action) {
         case "set_parent":
            parent_form = ar.parent_form;
         break;
         case "page_select":
            on_page_select();
         break;
         case "query_close":   // CP closing
            if (form.btn_save1.enabled)
            {
               var res = ctx.application.ui.message_box(parent_form, ctx.session.res_string("msg_record_set_query_save_record_set"), ctx.session.res_string("lbl_record_set_caption"), 35);
               ar.cancel = res == 2;
               if (res == 6 && book_processor != null)
                  on_save();
            }
         break;
         case "close":   // CP closed
            on_close();
         break;
      }
   }
   
   function on_page_select() {
      var bp_options = {
         "connector": book_processor ? book_processor.get_connector() : null
      };
      book_processor = new book_of_business_processor(ctx, bp_options);
      predefined_options = book_processor.get_predefined_options();
      parent_form.infobar.caption = ctx.session.res_string("record_set_tab_description");
      parent_form.infobar.visible = parent_form.toolbar.visible = false;
      parent_form.cp_pages.active_page = parent_form.cp_pages.pages.cp_busy_page;
      book_processor.save_default_books_if_empty(saved_books_retrieved, on_connector_failed);
   }
   
   function on_close() {
      if (book_processor)
         book_processor.abort();
   }
   
   function on_connector_failed() {
      // close Control Panel
      parent_form.close();
   }
   
   /**
   Switches back to active page UI from on_busy page with daisy.
   @type Function
   */
   function switch_back_from_daisy() {
      parent_form.cp_pages.active_page = parent_form.cp_pages.pages.cp_record_set_page;
      parent_form.infobar.visible = parent_form.toolbar.visible = true;
   }

   /**
   Enables/disables "Save" button based on detected changes and performed validations.
   @type Function
   */
   function validate_changes() {
      var enable_save_btn = true;
      var changes_found = false;
      // Detect changes
      if (saved_item_snapshot.length != current_item.length) {
         changes_found = true;
      } else {
         for (var i in current_item) {
            var current_item_options = current_item[i];
            var saved_item_snapshot_options = saved_item_snapshot[i];
            if (saved_item_snapshot_options.BookId != current_item_options.BookId || saved_item_snapshot_options.IncludeSubBooks != current_item_options.IncludeSubBooks) {
               changes_found = true;
               break;
            }
         }
      }
      
      if (!changes_found) {
         enable_save_btn = false;
      } else {
         // Run validations
         for (var i in current_item) {
            if (current_item[i].BookId === predefined_options.no_book_selected.BookId) {
               enable_save_btn = false;
               break;
            }
         }
      }
      // Enable/disable "Save" button
      form.btn_save1.enabled = enable_save_btn;
   }

   /**
   Builds a snapshot of current_item, which can later be used as saved item snapshot for detecting changes.
   @type Function
   */
   function rebuild_saved_item_snapshot() {
      var data_source = book_processor.get_data_source();
      var columns = data_source.columns.toArray();
      saved_item_snapshot = [];
      for (var key in current_item) {
         var snapshot_item = {};
         for (var i in columns)
            snapshot_item[columns[i]] = current_item[key][columns[i]];
         saved_item_snapshot.push(snapshot_item);
      }
   }
}

function book_of_business_processor(ctx, options) {
   options = options || {};
   
   var available_books, user_default_book, user_has_books;
   var record_set_types = [];
   var default_books = [];
   var data_source, connector = options.connector || null;
   var disconnectable = {};
   var book_predefined_options =
   {
      "team": {BookId: "", IncludeSubBooks: false},
      "no_book_selected": {BookId: null, IncludeSubBooks: null}
   };
   
   this.save_default_books_if_empty = function(on_after_saved_fn, on_save_failed_fn)
{
      var on_books_retrieved = function (retrieved_books) {
         save(retrieved_books, on_after_saved_fn);
      };
      this.retrieve_saved_or_default_books(on_books_retrieved, on_save_failed_fn);
   };
   
   this.retrieve_saved_or_default_books = function(on_books_retrieved_fn, on_err_fn)
{
      // Saving default visibility modes
      if (!connector)
         ctx.application.connector.async_get_remote_connector(0, form_helpers.disconnectable_handler(on_connector_ready, disconnectable));
      else
         on_connector_ready(connector);
         
      function on_connector_ready(c, err) {
         if (err) {
            ctx.ui.message_box(ctx.ui.app_window, err.message, ctx.session.res_string("books_retrieve_failed_title"), 0x10); // MB_OK | MB_ICONERROR
            if (on_err_fn)
               on_err_fn(err);
            return;
         }
         
         // Reset variables
         var saved_item = [];
         var default_prefilling = [];
         record_set_types = [];
         default_books = [];
         available_books = [];
         user_default_book = null;
         data_source = null;
         
         // Cache connector
         connector = c;

         // Retrieve remotely available books list and default books per type for current user
         create_data_source("Book", function(book_ds) {
            available_books = retrieve_books_picklist_from_datasource(book_ds);
            var books_count = 0;
            for (var _ in available_books) { books_count++; }
            user_has_books = books_count > 0;
            create_data_source("BookDefaults", function(BookDefaults_ds) {
               default_books = retrieve_books_picklist_from_datasource(BookDefaults_ds);
               on_books_ready();
            });
         });
         
         function on_books_ready()
         {
            // Configure list of supported types
            for (var type_id in default_books)
               record_set_types.push({type_id: type_id, sort_order: parseInt(default_books[type_id]["OrderNumber"])});
            record_set_types.sort(function(a, b){ return a.sort_order - b.sort_order; });

            // Get global default book
            create_data_source("::Defaults", function(defaults_ds) {
               // If no items found, proceed
               if (defaults_ds.record_count == 0) {
                  configure_default_books();
               } else {
                  var ds_item = defaults_ds.get_item_id(0);
                  connector.async_get_item("::Defaults", ds_item, function(){}, form_helpers.disconnectable_handler(function(defaults, err) {
                     if (err == null && defaults.DefaultBookName != "" && defaults.DefaultBookName != "All+") {
                        for (var id in available_books) {
                           if (available_books[id].Label == defaults.DefaultBookName) {
                              user_default_book = id;
                              break;
                           }
                        }
                     }
                     configure_default_books();
                  }, disconnectable));
               }
               
               function configure_default_books() {
                  helpers.for_each2(record_set_types, function(rs_type){
                     // If default book per type is not available set to global default book if available
                     if (default_books[rs_type.type_id].BookId == null && user_default_book != null) {
                        default_books[rs_type.type_id].BookId = user_default_book;
                        default_books[rs_type.type_id].IncludeSubBooks = !available_books[user_default_book].CanContainDataFlag && allow_include_subbooks(rs_type.type_id);
                     }
                     // Check if books of business are enabled
                     rs_type.books_enabled = default_books[rs_type.type_id] != null;
                     // Lookup default book for type if books enabled
                     if (rs_type.books_enabled)
                        rs_type.default_book = default_books[rs_type.type_id];

                     // Default prefilling
                     var book_available = rs_type.books_enabled && user_has_books;
                     var def_book_exists = default_book_exists(rs_type);
                     var prefill_default_book = book_available && def_book_exists;
                     apply_to_type(rs_type.type_id, function(item){
                        item.BookId = prefill_default_book ? rs_type.default_book.BookId : book_predefined_options.team.BookId;
                        item.IncludeSubBooks = prefill_default_book ? rs_type.default_book.IncludeSubBooks : book_predefined_options.team.IncludeSubBooks;
                     }, default_prefilling);
                  });

                  // Get saved item if found
                  create_data_source("Book.Type.Association", function(ds) {
                     // Make datasource global for future use
                     data_source = ds;
                     // If no saved items found, consider this is a first run and proceed next
                     if (data_source.record_count > 0) {
                        // Process found items
                        var items_processed = 0;
                        for (var i=0; i<data_source.record_count; i++) {
                           var ds_item = data_source.get_item_id(i);
                           connector.async_get_item("Book.Type.Association", ds_item, function(){}, form_helpers.disconnectable_handler(function(retrieved_item, err) {
                              if (err == null)
                                 saved_item.push(retrieved_item);
                              items_processed++;

                              // If all items retrieved
                              if (items_processed == data_source.record_count)
                                 configure_default_item();
                           }, disconnectable));
                        }
                     } else {
                        configure_default_item();
                     }
                     
                     // Compiles default visibility modes list
                     function configure_default_item() {
                        helpers.for_each2(record_set_types, function(rs_type){
                           // Trying to find saved mode
                           var item_found = false;
                           for (var key in saved_item) {
                              if (saved_item[key].TypeName == rs_type.type_id) {
                                 item_found = true;
                                 break;
                              }
                           }
                           // set to default mode if not found
                           if (!item_found)
                              apply_to_type(rs_type.type_id, function(item){
                                 for (var key in default_prefilling) {
                                    if (default_prefilling[key].TypeName == item.TypeName) {
                                       item.BookId = default_prefilling[key].BookId;
                                       item.IncludeSubBooks = default_prefilling[key].IncludeSubBooks;
                                       break;
                                    }
                                 }
                              }, saved_item);
                        });
                        
                        on_books_retrieved_fn(saved_item);
                     }
                  });
               }
            });
         }
            
         function retrieve_books_picklist_from_datasource(ds) {
            var result = {};
            var count = ds.record_count;
            var _columns = ds.columns.toArray();
            var columns = {};
            for (var i=0; i < _columns.length; i++) {
               columns[_columns[i]] = i;
            }
            for (var i=0; i < count; i++) {
               var row = ds.get_item_fields(i).toArray();
               result[get_value(row)] = get_item(row);
            }
            
            function get_value(row)
            {
               return row[columns["Value"]];
            }
            function get_item(row)
            {
               var item = {};
               helpers.for_each2(_columns, function(fld_name){
                  item[fld_name] = row[columns[fld_name]];
               });
               return item;
            }
            return result;
         }
         
         function create_data_source(type_id, fn) {
            var ds = connector.create_data_source(type_id);
            ds.on_changed.connect(form_helpers.disconnectable_handler(function() { fn(ds); }, disconnectable));
            ds.enabled = true;
            ds.refresh(100, 600000);
            ds.enabled = false;
         }
      }
   }

   function save(item, on_after_saved_fn) {
      var saved_items_count = 0;
      for (var key in item) {
         connector.async_put_item(item[key], on_progress, form_helpers.disconnectable_handler(on_put_item_complete, disconnectable));
      }
      if (item.length == 0)
         on_after_saved_fn(item);
      
      function on_progress() {}
      function on_put_item_complete(saved_book) {
         // Synchronize new selected value with local storage
         var user_selected_book = get_ol_storage_rs_book(ctx, saved_book.TypeName) || ctx.session.create_item("Book.Type.Association");
         user_selected_book.TypeName = saved_book.TypeName;
         user_selected_book.BookId = saved_book.BookId;
         user_selected_book.IncludeSubBooks = saved_book.IncludeSubBooks;
         user_selected_book.save();
         
         saved_items_count++;
         if (saved_items_count == item.length)
            on_after_saved_fn(item);
      }
   }
   this.save = save;
   
   this.get_types_list = function () {
      return record_set_types;
   }

   this.get_data_source = function () {
      return data_source;
   }
   
   this.get_connector = function () {
      return connector;
   };
   
   this.get_available_books = function () {
      return available_books;
   };
   
   this.user_has_books = function () {
      return user_has_books;
   }
   
   this.get_predefined_options = function () {
      return book_predefined_options;
   }
   
   this.abort = function() {
      disconnectable.disabled = true;
   }
   
   function allow_include_subbooks(type) {
      return allow_includesubbooks[type] || false;
   }
   this.allow_include_subbooks = allow_include_subbooks;
   
   /**
   Checks whether default book is defined for a type.
   @param type Type name to check default book for
   @returns {Boolean} Does default book exist for a type
   @type Function
   */
   function default_book_exists(type) {
      // Books are disabled
      if (!type.books_enabled)
         return false;
      // No default book
      var book_id = type.default_book.BookId;
      if (book_id == null)
         return false;
      // accessible book && the book that can contain data or with "Include Sub-Items" enabled by administrator
      var book = available_books[book_id];
      if (book != null && (book.CanContainDataFlag || type.default_book.IncludeSubBooks))
         return true;
      // The book that cannot contain data and "Include Sub-Items" for it is disabled by administrator
      return false;
   }
   this.default_book_exists = default_book_exists;
   
   /**
   Applies a function to a specific type records set option in destination item. if not yet exists, creates "team" records set option for a type (default option).
   @param type_id Records set option type name
   @param {Function} f Function to call over an item
   @param dest Destination object to lookup an item in.
   @type Function
   */
   function apply_to_type(type_id, f, dest) {
      // Try to find item in dest
      var item = null;
      for (var i in dest) {
         if (dest[i].TypeName == type_id) {
            item = dest[i];
            break;
         }
      }
      // Create item if not found
      if (item == null) {
         item = connector.create_item("Book.Type.Association");
         item.TypeName = type_id;
         item.BookId = book_predefined_options.team.BookId;
         item.IncludeSubBooks = book_predefined_options.team.IncludeSubBooks;
         dest.push(item);
      }
      // Apply function
      f(item);
   }
   this.apply_to_type = apply_to_type;
}

function get_ol_storage_rs_book(ctx, type_id) {
   return ctx.session.find_item("Book.Type.Association", ctx.session.create_expression("TypeName", "eq", type_id));
}

Oracle CRM On Demand Desktop Administration Guide, Version 5.2 Copyright © 2017, Oracle and/or its affiliates. All rights reserved. Legal Notices.