Jelajahi Sumber

HUE-211. Add ability to load content into an app via Ajax without loading the whole screen.

Aaron Newton 15 tahun lalu
induk
melakukan
d28cb99509

+ 50 - 0
apps/jframegallery/src/jframegallery/templates/ajax-target.html

@@ -0,0 +1,50 @@
+{% comment %}
+Licensed to Cloudera, Inc. under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  Cloudera, Inc. licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+{% endcomment %}
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+	<head>
+		<title>Ajax Target</title>
+	</head>
+	<body>
+		<div class="jframe_padded">
+			<a href="/jframegallery/partial_refresh.mako?sleep=1" data-ajax-target=".ajax_target">Load some content into the div below</a>
+			<div style="border: 1px solid #000; padding: 10px; margin: 10px 0px;" class="ajax_target">
+				This content is replaced whenever you click the link above.
+			</div>
+			<p>
+				Note that once you load content into the div above, hitting refresh destroys that content.
+			</p>
+			<hr/>
+			<a href="/jframegallery/partial_refresh.mako?sleep=1" data-ajax-replace=".ajax_replace div">Replace the blue box below.</a>
+			<div style="border: 1px solid #000; padding: 10px; margin: 10px 0px;" class="ajax_replace">
+				<div style="padding: 10px; background: #99f;">This gets replaced by the response</div>
+			</div>
+			<a href="/jframegallery/partial_refresh.mako?sleep=1" data-ajax-append=".ajax_append div">Add the response after the blue box below.</a>
+			<div style="border: 1px solid #000; padding: 10px; margin: 10px 0px;" class="ajax_append">
+				<div style="padding: 10px; background: #99f;">The response gets appended after this box</div>
+			</div>
+			<hr/>
+			<a href="/jframegallery/partial_refresh.mako?sleep=1" data-ajax-target=".ajax_filter" data-ajax-filter="textarea">This link loads the same url as the others, but only the textarea is inserted into the box below</a>
+			<div style="border: 1px solid #000; padding: 10px; margin: 10px 0px;" class="ajax_filter">
+				This box is replaced with a textarea when you click the 
+			</div>
+			<hr/>
+			<a href="/jframegallery/partial_refresh.mako" data-ajax-target=".nothing_here">This is also an ajax link, but it's target is not found, so it falls back to being a regular link.</a>
+		</div>
+	</body>
+</html>

+ 28 - 0
apps/jframegallery/src/jframegallery/templates/ajax.spinner.target.html

@@ -0,0 +1,28 @@
+{% comment %}
+Licensed to Cloudera, Inc. under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  Cloudera, Inc. licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+{% endcomment %}
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+	<head>
+		<title>Ajax Spinner Target</title>
+	</head>
+	<body>
+		<div class="jframe_padded">
+			<a style="display:block; border: 1px solid #000; width: 100px; padding: 50px 10px; text-align:center;" href="/jframegallery/ajax.spinner.target.html?sleep=1" data-spinner-target=".spinnerTarget" class="spinnerTarget">Click to reload with the spinner only on this box</a>
+		</div>
+	</body>
+</html>

+ 12 - 22
desktop/core/static/js/Source/CCS/CCS.JBrowser.js

@@ -21,39 +21,29 @@ requires:
  - /CCS.JFrame
  - Widgets/ART.Browser
  - Widgets/ART.SolidWindow
+ - /CCS.ContextMenu
+
  - /CCS.JFrame.Alert
- - /CCS.JFrame.ArtButtons
+ - /CCS.JFrame.PartialRefresh
+ - /CCS.JFrame.Prompt
+
  - /CCS.JFrame.AutoRefresh
+ - /CCS.JFrame.DoubleClickDelegate
+ - /CCS.JFrame.FormRequest
+ - /CCS.JFrame.ToggleHistory
+
+ - /CCS.JFrame.AjaxLoad
  - /CCS.JFrame.CheckAllOrNone
  - /CCS.JFrame.Chooser
- - /CCS.JFrame.Collapsible
  - /CCS.JFrame.ConfirmAndPost
- - /CCS.JFrame.ContextMenu
- - /CCS.JFrame.DataGroupToggle
- - /CCS.JFrame.DoubleClickDelegate
  - /CCS.JFrame.FakeRefresh
- - /CCS.JFrame.FilterInput
- - /CCS.JFrame.FormRequest
- - /CCS.JFrame.FormValidator
- - /CCS.JFrame.FitText
- - /CCS.JFrame.HtmlTable
- - /CCS.JFrame.Input
+ - /CCS.JFrame.LivePath
  - /CCS.JFrame.Nav
- - /CCS.JFrame.OverText
- - /CCS.JFrame.PartialRefresh
- - /CCS.JFrame.Prompt
+ - /CCS.JFrame.NoScroll
  - /CCS.JFrame.PromptAndPost
  - /CCS.JFrame.Refresh
- - /CCS.JFrame.SelectWithOther
- - /CCS.JFrame.SideBySideSelect
- - /CCS.JFrame.SizeTo
- - /CCS.JFrame.SplitView
  - /CCS.JFrame.SubmitLink
- - /CCS.JFrame.SubmitOnChange
- - /CCS.JFrame.Tabs
  - /CCS.JFrame.Target
- - /CCS.JFrame.Tips
- - /CCS.JFrame.ToggleHistory
 script: CCS.JBrowser.js
 
 ...

+ 5 - 9
desktop/core/static/js/Source/CCS/CCS.JFrame.js

@@ -18,18 +18,14 @@
 description: JFrame--Configurable "container" for simple HTML pages, within the CCS framework.
 provides: [CCS.JFrame]
 requires: 
- - Core/Request.JSON
- - More/URI
+ - Core/Request
  - More/Element.Delegation
- - More/Fx.Scroll
  - More/Elements.From
- - clientcide/Collapsible
- - Widgets/ART.Alerts
+ - More/Fx.Scroll
  - More/String.Extras
- - Widgets/ART.SplitView
- - More/HtmlTable.Sort
- - More/HtmlTable.Select
  - More/Spinner
+ - clientcide/Collapsible
+ - Widgets/ART.Alerts
  - Widgets/Behavior
  - Widgets/Behavior.Accordion
  - Widgets/Behavior.ArtButton
@@ -59,7 +55,7 @@ requires:
  - /Behavior.Tabs
  - /Behavior.Tips
  - /CCS
- - /CCS.ContextMenu
+
 script: CCS.JFrame.js
 ...
 */

+ 1 - 1
desktop/core/static/js/Source/CCS/CCS.js

@@ -18,7 +18,7 @@
 description: CCS Configuration Options
 provides: [CCS]
 requires: [clientcide/StickyWin, Widgets/ART.Popup, Core/Element.Event, Core/Request.HTML,
-  More/Spinner, Core/Selectors]
+  More/Spinner, Core/Selectors, More/URI]
 script: CCS.js
 
 ...

+ 2 - 1
desktop/core/static/js/Source/JFrameFilters/CCS.JFrame.AutoRefresh.js

@@ -33,7 +33,8 @@ CCS.JFrame.addGlobalFilters({
 		//get the first input.autorefresh and use its value as the duration before
 		//it auto refreshes the input. if span.sec_to_autorefresh is present, fill its
 		//contents with the number of seconds until a refresh.
-		if (content && content.meta) {
+		var ignoreAutoRefresh = content && content.options && content.options.ignoreAutoRefresh;
+		if (!ignoreAutoRefresh && content && content.meta) {
 			var sec, url;
 			content.meta.each(function(meta) {
 				var parts = meta.get('content').split(';');

+ 113 - 0
desktop/core/static/js/Source/JFrameLinkers/CCS.JFrame.AjaxLoad.js

@@ -0,0 +1,113 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+/*
+---
+description: Provides functionality for links that load content into a target element via ajax.
+provides: [CCS.JFrame.AjaxLoad]
+requires: [/CCS.JFrame]
+script: CCS.JFrame.AjaxLoad.js
+...
+*/
+
+(function(){
+	//if we are loading a link via ajax, we either replace, append, or inject.
+
+	var linkers = {};
+
+	['append', 'replace', 'target'].each(function(action){
+		linkers['data-ajax-' + action] = function(event, link){
+			var target = $(this).getElement(link.get('data', 'ajax-' + action));
+			if (!target) {
+				link.erase('data-ajax-' + action);
+				dbug.log('could not ' + action + ' the target element with response; element matching selector %s was not found', link.get('data', 'ajax-' + action));
+				this.callClick(event, link, true);
+			}
+			ajaxLoad.call(this, event, link, target, action);
+		};
+	});
+
+	CCS.JFrame.addGlobalLinkers(linkers);
+
+	/*
+		loads the contents of a link into a specific target
+		* event - the event object from the link click
+		* link - the link clicked
+		* target - where to put the response
+		* action - (string; optional) either 'append', 'replace', or 'update' (defaults to 'update')
+		
+		notes:
+		* replace means destroy the target and replace it entirely with the response.
+		* append means leave everything in place and inject the response after the target.
+		* update means empty the target and fill it with the response
+		* links with a "data-ajax-filter" property will inject only the elements that match the selector it specifies.
+		  For example, if you have a table that you want to add rows to, and your request returns an HTML document that
+		  includes an entire table, you would specify data-ajax-filter="table tbody tr" to only inject the rows from
+		  the body in the response.
+	*/
+
+	var ajaxLoad = function(event, link, target, action){
+
+		action = action || 'update';
+		var requestTarget = target;
+		if (action != 'update') requestTarget = new Element('div');
+
+
+		var options = {
+			filter: link.get('data', 'ajax-filter'),
+			requestPath: link.get('href'),
+			spinnerTarget: requestTarget,
+			target: requestTarget,
+			ignorePartialRefresh: true,
+			ignoreAutoRefresh: true,
+			suppressLoadComplete: true,
+			retainPath: true,
+			callback: function(data){
+				switch(action){
+					case 'replace':
+						//reverse the elements and inject them
+						//reversal is required since it injects each after the target
+						//pushing down the previously added element
+						data.elements.reverse().injectAfter(target);
+						target.destroy();
+						break;
+					case 'append':
+						//see note above in 'replace' case as to why we use reverse here
+						data.elements.reverse().injectAfter(target);
+						break;
+					//do nothing for update, as Request.HTML already does it for you
+				}
+				var state = {
+					event: event,
+					link: link,
+					target: target,
+					action: action
+				};
+				//pass along the data that came back from JFrame's response handler as well as the state of this ajax load.
+				this.fireEvent('ajaxLoad', [data, state]);
+				this.behavior.fireEvent('update', [data, state]);
+			}.bind(this)
+		};
+		var spinnerTarget = link.get('data', 'spinner-target');
+		if (spinnerTarget) {
+			spinnerTarget = $(this).getElement(spinnerTarget);
+			options.spinnerTarget = spinnerTarget;
+		}
+
+		this.load(options);
+
+	};
+
+})();

+ 1 - 0
desktop/core/static/js/package.yml

@@ -33,6 +33,7 @@ sources: [
   Source/UI/StickyWin.Drawer.js,
   Source/UI/StickyWin.UI.Solid.js,
   Source/UI/ThumbTack.js,
+  Source/JFrameLinkers/CCS.JFrame.AjaxLoad.js,
   Source/JFrameLinkers/CCS.JFrame.CheckAllOrNone.js,
   Source/JFrameLinkers/CCS.JFrame.Chooser.js,
   Source/JFrameLinkers/CCS.JFrame.ConfirmAndPost.js,