PageSourceSearch

https://sdccd.edu/_resources/ou/editor/select-lists/select-lists.js

js sdccd.edu collected 2026-10-01 11:58:03 UTC 9,574 bytes, 188 lines download raw bytes

1$(function(){
2	// App globals
3	if(/site=([^&]+)/.test(window.location.href)){
4		var site = window.location.href.match(/site=([^&]+)/)[1]; // automatically set site based on staging url.
5	}else{
6		var site = 'www'; // default to www if fails to retreive from staging url.
7	}
8	var thisScriptsPath = $('script[src*="select-lists.js"]').attr('src').replace('select-lists.js', ''); // set the path of this script so we can determine the path of the JSON files.
9	var JSONPath = thisScriptsPath + 'json/'; // path where the JSON data files are kept.
10	var APIJSONPath = window.location.origin + '/files/source?site=' + site + '&path=' + encodeURIComponent(JSONPath); // OU API path for retrieving JSON files from staging
11	var JSONfileExt = 'json'; // JSON data file extension.
12	var selectLists = {}; // this stores the html code for each select lists.
13	var defaultText = 'Nothing'; // this is used when an option is set to empty string.
14	var suppressAlertMessages = false; // used to suppress future alert messages after an alert message is displayed.
15	
16	// Event listeners [START]
17	$('body').on('mouseenter', 'table[class^="ou-"]', function(){
18		/*
19			A mouseenter event is used to trigger the loading of the select list data via ajax when
20			the mouse enters over a table transformation. This is necessary since the table transformation
21			markup is not part of the DOM until an editable region edit button is clicked. I felt this
22			method is more reliable then using the domSubtreeModified event.
23		*/
24		loadSelectLists();
25		disableKeyboardEntry();
26		trimContent();
27	});
28	
29	$('body').on('click', 'table[class^="ou-"] [data-select-list]', function(){
30		if($(this).children('ul.ou-select-list').length) return; // if a select list is already open for this cell then just return.
31		
32		// retrieves the current value, loads the specified select list, adds an active class to the option that matches the current value and scrolls to the location of that option.
33		var selectList = $(this).data('select-list');
34		var selectedOption = trim($(this).text());
35		setOption(); // run setOption() to close any open select lists before opening this new one.
36
37		if(selectLists[selectList] == '') return; // No select list content so just return.
38
39		$(this).html(selectLists[selectList]);
40		$('ul.ou-select-list li[data-value="' + selectedOption + '"]').addClass('active');
41		
42		if(!$('ul.ou-select-list li.active').length){
43			$('ul.ou-select-list li:first').addClass('active');
44		}
45		
46		if (/Edge\/\d./i.test(navigator.userAgent)){
47			/*
48				On Microsoft Edge apply this workaround so that the scroll to active feature will work. Microsoft tries to "help"
49				by automatically scrolling to the cursor position. So let's trigger the autoscroll to happen again after a half second.
50			*/
51			setTimeout(function(){
52				$('ul.ou-select-list').scrollTop($('ul.ou-select-list').scrollTop() + $('ul.ou-select-list li.active').position().top); // automatically scroll to selected option.
53			}, 500);
54		}
55			
56		$('ul.ou-select-list').scrollTop($('ul.ou-select-list').scrollTop() + $('ul.ou-select-list li.active').position().top); // automatically scroll to selected option.
57		
58		$('ul.ou-select-list li').on('click', function(){
59			$('ul.ou-select-list li.active').removeClass('active');
60			$(this).addClass('active');
61			setOption();
62		});
63	});
64	
65	$(document).click(function(e) {
66		// this closes the select list whenever the user clicks anywhere outside of it.
67		var target = e.target;
68
69		if (!$(target).is('table[class^="ou-"] [data-select-list]') && !$(target).parents().is('table[class^="ou-"] [data-select-list]')) {
70			setOption();
71		}
72	});
73	// Event listeners [END]
74	
75	// App specific functions [START]
76	function loadSelectLists(){
77		// retrieves list data for the all the select lists via inline, js include or ajax declaration methods. Then it builds the html code and caches it in a variable named "selectLists".
78		$('[data-select-list]').each(function() {
79			var selectList = $(this).data('select-list');
80			if(!selectLists.hasOwnProperty(selectList)){
81				selectLists[selectList] = '';
82				
83				if(selectList.split(',').length > 1){ // "Inline" list declaration method used since commas exist in data attribute value.
84					selectLists[selectList] = buildSelectList(selectList.split(','), '{{text}}'); // no default lineTemplate declared when inline method is used so just set to {{text}}.
85				}else{ // "JSON Files" list declaration method is the default if inline method is not used.
86					$.getJSON(APIJSONPath + selectList + '.' + JSONfileExt, function(data){
87						data = $.parseJSON(data.source); // OU API returns the files source wrapped in JSON so we now need to grab the source keys value and parse the value to JSON.
88						if('path' in data){
89							getOptionsByPath(selectList, data);
90						}else{
91							selectLists[selectList] = buildSelectList(data.options, ('lineTemplate' in data) ? data.lineTemplate : '{{text}}');	
92						}
93					}).fail(function(data){
94						if(!suppressAlertMessages && data.responseJSON.code == 'ACCESS_DENIED'){
95							suppressAlertMessages = true; // suppress future alert messages.
96							alert('Unable to load Select List data due to access restrictions.\n\nPlease ask your administrator to change the Access Group to "Everyone" for: ' + JSONPath);
97						}
98					});
99				}
100			}
101		});
102	}
103	
104	function disableKeyboardEntry(){
105		if(tinyMCE.activeEditor.OU == undefined || tinyMCE.activeEditor.OU.keyboardEntryDisabled != true){
106			tinyMCE.activeEditor.on('keydown', function(e){
107				if($(e.target).find('ul.ou-select-list').length){
108					e.preventDefault();
109				}
110				
111				if($(tinyMCE.activeEditor.selection.getNode()).is('[data-select-list]')){
112					e.preventDefault();
113				}
114			});
115			
116			tinyMCE.activeEditor["OU"] = {'keyboardEntryDisabled': true};
117		}
118	}
119
120	function trimContent(){
121		$('table[class^="ou-"] [data-select-list]').filter(function(){
122			return (trim($(this).text()) == '');
123		}).html('');
124	}
125	
126	function getOptionsByPath(selectList, data){
127		var options = [':' + defaultText + ':{{text}}']; // Make sure to include an empty option to start off with.
128		$.getJSON(window.location.origin + '/files/list?site=' + site + '&path=' + escape(data.path) + '&images=true', function(fileData){
129			fileData = fileData.entries; // we only need the entries property
130			for(var i=0; i<fileData.length; i++){
131				if(!fileData[i].is_directory){
132					options.push(fileData[i].remote_path + ':' + escape(fileData[i].http_path));
133				}
134			}
135			
136			selectLists[selectList] = buildSelectList(options, ('lineTemplate' in data) ? data.lineTemplate : '{{text}}');
137		});
138	}
139
140	function buildSelectList(options, defaultLineTemplate){
141		// builds the select list html code
142		
143		if(!Array.isArray(options) || options.length == 0) return ''; // If options argument is not an array then just return empty string. 
144		
145		var selectListHTML = '<ul class="ou-select-list">';
146		for(var i=0; i<options.length; i++){
147			var aOption = options[i].split(':');
148			var value = trim(aOption[0]);
149			var text = trim(aOption[0]);
150			var lineTemplate = defaultLineTemplate;
151
152			if(aOption.length > 1){
153				// text was included in data so use it
154				text = trim(aOption[1]);
155			}
156			
157			value = unescape(value);
158			text = unescape(text);
159
160			if(aOption.length == 3){
161				// lineTemplate was included in data so use it.
162				lineTemplate = trim(aOption[2]);
163			}
164			
165			if(text == '') text = defaultText; // Set display text to defaultText if it's an empty string.
166
167			selectListHTML += '<li data-value="' + value + '">' + lineTemplate.replace(/{{value}}/g, value).replace(/{{text}}/g, text) + '</li>';
168		}
169		selectListHTML += '</ul>';
170		return selectListHTML;
171	}
172	
173	function setOption(){
174		$('ul.ou-select-list').each(function(){
175			$(this).closest('td').text(trim($(this).find('li.active').data('value')));
176		});
177	}
178	// App specific functions [END]
179	
180	// Utility functions
181	function trim(s){
182		return s.toString().replace(/^\s+|\s+$/g, '');
183	}
184
185});
186
187
188$(function(){function t(){return!e(this).is('[data-table-separator-options~="disable"]')}function e(t){var e=$(t).parent().closest("[data-table-separator-options]");return e.length||(e=$(t).closest(".ou-justedit-region").prevAll().filter("ouc\\:div").first()),e}$("body").on("click",".ou-table-separator",function(){var t=$(this),a=e(this).is('[data-table-separator-options~="clone"]'),o=e(this).is('[data-table-separator-options~="empty"]');a?(t.prev().length?$clone=t.prev().clone():$clone=t.next().clone(),o&&$clone.find("td").not(":has(> table)").text(" "),$clone.hide(),t.replaceWith($clone.fadeIn())):(t.replaceWith('<p><br data-mce-bogus="1" data-focus-me="1"></p>'),tinyMCE.activeEditor.selection.select(tinyMCE.activeEditor.dom.select("[data-focus-me]")[0]),$("[data-focus-me]").removeAttr("data-focus-me"),tinyMCE.activeEditor.selection.collapse(!1)),tinyMCE.activeEditor.isNotDirty=!1}),$("body").on("mouseenter",".ou-justedit-region",function(){$(".ou-justedit-region table:first-child, .ou-justedit-region table + table").filter(t).before('<div class="ou-table-separator mceNonEditable" data-mce-contenteditable="false" data-mce-bogus="1"></div>'),$(".ou-justedit-region table:last-child").filter(t).after('<div class="ou-table-separator mceNonEditable" data-mce-contenteditable="false" data-mce-bogus="1"></div>');var a=$(".ou-table-separator + .ou-table-separator");a.prev().remove(),a.filter(function(){return!e(this).is('[data-table-separator-options~="clone"]')}).replaceWith('<p><br data-mce-bogus="1"></p>'),$("div.ou-table-separator > table").each(function(){var t=$(this).parent();t.replaceWith(t.html())})})});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.