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)); }
|