OpenLaszlo <html> tag / iframe integration and JavaScript calls - dhtml

I am trying to call one javascript function present in the html data that i am inserting but i am always getting an error getLoaded is not a method. I have attached the code snippet. What is wrong ?
<canvas width="100%" height="100%" >
<simplelayout axis="y" spacing="2"/>
<button>Set HTML
<handler name="onclick">
<![CDATA[
if (canvas.main) {
canvas.main.setAttribute('html', '<html><head><style type="text/css">body {background-color: #ffffff;}</style><script>function getLoaded(){ return document.images.length;}</script></head><body><img id="imageTag" ></img></body></html>');
}
]]>
</handler>
</button>
<button>test
<handler name="onclick">
<![CDATA[
if (canvas.main) {
var del = new LzDelegate(this,'handlerFunc');
canvas.main.callJavascript('getLoaded',del);
}
]]>
</handler>
</button>
<method name="handlerFunc" args="retVal">
console.log("handlerFunc", retVal);
</method>
<html name="main" x = "50" y="50" width="600" height="400" >
<handler name="oninit">
this.bringToFront();
</handler>
</html>
</canvas>

Here is a solution which works for the both the SWF10 and DHTML runtime. I've tested with IE 9, Firefox and Chrome.
There are two problems with your code:
1) The HTML snippet you are assigning to the #html attribute of the <html> tag should not contain a full HTML document structure. Here is the JavaScript from the iframemanager.js library (part of OpenLaszlo) which is used to assign the HTML snippet to the iFrame:
,setHTML: function(id, html) {
// must be called after the iframe loads, or it will be overwritten
if (html) {
var win = lz.embed.iframemanager.getFrameWindow(id);
if (win) {
win.document.body.innerHTML = html;
}
}
}
As you can see, the value of the html parameter is assigned to the innerHTML of the body element. Therefore it's sufficient to only include the body of the HTML document you are generating.
2) If you want to add JavaScript sections to an iFrame, you cannot inline those into the HTML code you want to assign to the document, but have to create a 'script' element as you can see in the full example below. If you want to support the SWF runtime as well, the most efficient way is to create a small external JavaScript function has a helper function as shown below.
There are two files I'm creating for this solution. The LZX file, and an external JavaScript file called iFrameHelperFunction.js.
Here is a modified version of your LZX file:
<canvas width="100%" height="100%" >
<wrapperheaders>
<script type="text/javascript" src="iFrameHelperFunction.js"></script>
</wrapperheaders>
<simplelayout axis="y" spacing="2"/>
<button>Set HTML
<handler name="onclick">
<![CDATA[
if (canvas.main) {
// Create the HTML content; do not include <html><head><body> structure here,
// since setting the 'html' attribute of an OpenLaszlo <html> tag will set
// the innerHTML property of the iFrame's document.body.
var innerHTML = '<style type="text/css">body {background-color: #ff0000;}</style>'
+ '<img id="imageTag" src="https://www.google.com/images/srpr/logo3w.png"></img>',
jsCode = "function getLoaded() { alert('inside getLoaded()'); return 'getLoaded was called'; }";
canvas.main.setAttribute('html', innerHTML);
lz.Browser.callJS('addJavaScriptToFrame("' + canvas.main.iframeid + '", ' + jsCode + ')');
}
]]>
</handler>
</button>
<button>test
<handler name="onclick">
<![CDATA[
if (canvas.main) {
var del = new LzDelegate(canvas, 'handlerFunc');
canvas.main.callJavascript('getLoaded', del);
}
]]>
</handler>
</button>
<method name="handlerFunc" args="retVal">
Debug.info("handlerFunc", retVal);
</method>
<html name="main" x = "50" y="50" width="600" height="200" >
<handler name="oninit">
this.bringToFront();
</handler>
</html>
</canvas>
First, I'm adding my custom JavaScript file to the page:
<wrapperheaders>
<script type="text/javascript" src="iFrameHelperFunction.js"></script>
</wrapperheaders>
Then the HTML snipped for the iFrame is set, similar to your code. But any JavaScript which is added to iFrame HTML page has to be added using a helper function addJavaScriptToFrame defined in iFrameHelperFunction.js:
function addJavaScriptToFrame(frameId, jsCode) {
var iframeWin = lz.embed.iframemanager.getFrameWindow(frameId);
doc = iframeWin.document;
// Scripts can not be inlined in HTML snippets, but must be created through JavaScript
var scriptEl = doc.createElement('script');
// The JavaScript function or code you want to add
scriptEl.text = jsCode;
// Append the script to the head of the iFrame document
doc.firstChild.appendChild(scriptEl);
}
The call to add the JavaScript to the iFrame in the LZX file:
lz.Browser.callJS('addJavaScriptToFrame("' + canvas.main.iframeid + '", ' + jsCode + ')');
Click the "Set HTML" button to set the content of the frame, and then click the "test" button to make the call to the getLoaded() function inside the iFrame.

Related

How to change the image on page refresh

I want to change the set of 5 image on page refresh called in html.
the images should called this under the body tag:
<img src="images/side-logos/1.jpg" alt="">
<img src="images/side-logos/2.jpg" alt="">
<img src="images/side-logos/4.jpg" alt="">
<img src="images/side-logos/5.jpg" alt="">
I want to called the set of images under the body tag not in javascript.
I have searched a lot on website but everyone calling the image in javascript not under the body tag.
So Please help me if anyone has the solutions for it.
just replace onclick event with window refresh event
HTML
<div id="box">
<img id="image" />
</div>
<br />
<input type="button" value="Randomize!" onClick="randImg()" />
JS
var images = [
"http://static.ddmcdn.com/gif/lightning-gallery-18.jpg",
"http://static.ddmcdn.com/gif/lightning-gallery-19.jpg",
"http://static.ddmcdn.com/gif/lightning-gallery-20.jpg",
"http://static.ddmcdn.com/gif/lightning-gallery-17.jpg"];
function randImg() {
var size = images.length
var x = Math.floor(size * Math.random())
document.getElementById('image').src = images[x];
}
randImg();
demo
EDIT
new_demo
Unfortunateley, you can only do this with javascript.
To do that, here is some code that is placed in the tags
<script type="text/javascript">
function Randomize() {
var images = new Array("one.jpg","two.jpg","three.jpg","four.jpg");
var imageNum = Math.floor(Math.random() * images.length);
document.getElementById("divid").style.backgroundImage = "url('" + images[imageNum] + "')";
}
window.onload = Randomize;
</script>
The name of the images shoukd be in the images array and the "divid" is where you want the images to appear.

Dynamic selectone in alfresco share

For a form in Alfresco share, I want a dropdown box that is filled with custom options depending on the value of a field earlier up in the form.
My form would have at least two fields. The first one a textbox, where a unique code must be entered. When that is done, the second one, a select box, must load it's options using the entered code.
The data backing this requirement is stored in a Data list. I have also made it available through a webscript (along the lines of /getOptions/{uniqueCode, returning a JSON array of the valid options.
Now, I am a bit stuck on how to build the part of the form that will watch for status changes on the code textfield, and reload the dropdown box. I can think of some javascript, but I don't even know where to start changing/adding files.
I've looked through the FDK, where I found the selectone ftl. Unfortunately, this supports only fixed options.
My implementation based on my chosen answer
This is very similar to what I was already doing, I had hoped to be able to do this on the server side, without including the extra round-trip. So far, this is the best I have though.
share-config-custom.xml
I define the form here, and point the property I want to be my selectone to my own custom field template. I pass a parameter ds to it, dataSource, which holds the path to my webscript.
<config evaluator="node-type" condition="my:contentType">
<forms>
<form>
<field-visibility>
<show id="my:code" />
<show id="my:description" />
</field-visibility>
<appearance>
<set id="general" appearance="bordered-panel" label="General" />
<field id="my:description" set="general">
<control template="/org/alfresco/components/form/controls/customSelectone.ftl">
<control-param name="ds">/alfresco/service/mark/cache/options</control-param>
</control>
</field>
</appearance>
</form>
</forms>
customSelectone.ftl
My custom ftl has three major steps. First, it receives the ftl parameter I passed from share config custom and assigns it to a local variable. Then it places a html <select>box as a field, and finally, it executes a call to my webscript for the possible options.
Parameter
<#if field.control.params.ds?exists><#assign ds=field.control.params.ds><#else><#assign ds=''></#if>
html
<style type="text/css">
#${fieldHtmlId}-AutoComplete {
width:${width}; /* set width here or else widget will expand to fit its container */
padding-bottom:2em;
}
</style>
<div class="form-field">
<#-- view form -->
<#if form.mode == "view">
<div class="viewmode-field">
<#if field.mandatory && !(field.value?is_number) && field.value == "">
<span class="incomplete-warning"><img src="${url.context}/components/form/images/warning-16.png" title="${msg("form.field.incomplete")}" /><span>
</#if>
<span class="viewmode-label">${field.label?html}:</span>
<span class="viewmode-value">${field.value?html}</span>
</div>
<#else>
<#-- alternative: if form.mode == "edit" -->
<#-- Create/edit form -->
<label for="${fieldHtmlId}">${field.label?html}:<#if field.mandatory><span class="mandatory-indicator">${msg("form.required.fields.marker")}</span></#if></label>
<div id="${fieldHtmlId}-AutoComplete">
<#-- Label to hold error messages from the javascript -->
<p style="color:red" id="${fieldHtmlId}-scriptError"></p>
<select id="${fieldHtmlId}" name="${field.name}"
<#if field.control.params.styleClass?exists>class="${field.control.params.styleClass}"</#if>
<#if field.description?exists>title="${field.description}"</#if>
<#if field.control.params.size?exists>size="${field.control.params.size}"</#if>
<#if field.disabled>disabled="true"</#if> >
<#-- Add the field's current value if it has one as an option -->
<option>${field.value}</option>
</select>
<div id="${fieldHtmlId}-Container"></div>
</div>
</div>
Javascript
<script type="text/javascript">//<![CDATA[
(function()
{
<#-- This references the code field from the form model. For this, the -->
<#-- share config must be set to show the field for this form. -->
<#if form.fields.prop_my_code??>
var code = "${form.fields.prop_my_code.value}";
<#else>
var code = 0;
</#if>
// get code
if(code === null || code === "") {
document.getElementById('${fieldHtmlId}-scriptError').innerHTML = 'No description available.';
return;
}
// Create webscript connection using yui connection manager
// Note that a much more elegant way to call webscripts using Alfresco.util is
// available in the answers here.
var AjaxConnectionManager = {
handleSuccess:function(o) {
console.log('response: '+o.responseText);
this.processResult(o);
},
handleFailure:function(o) {
var selectBox = document.getElementById('${fieldHtmlId}');
var i;
document.getElementById('${fieldHtmlId}-scriptError').innerHTML = 'Descriptions not available.';
},
startRequest:function() {
console.log('webscript call to ${ds} with params code='+code);
YAHOO.util.Connect.asyncRequest('GET', "${ds}?typecode="+code, callback, null);
},
processResult:function(o) {
var selectBox = document.getElementById('${fieldHtmlId}');
var jso = JSON.parse(o.responseText);
var types = jso.types;
console.log('adding '+types.length+' types to selectbox '+selectBox);
var i;
for(i=0;i<types.length;i++) {
// If the current field's value is equal to this value, don't add it.
if(types[i] === null || types[i] === '${field.value}') {
continue;
}
selectBox.add(new Option(types[i], types[i]));
}
}
}
// Define callback methods
var callback = {
success:AjaxConnectionManager.handleSuccess,
failure:AjaxConnectionManager.handleFailure,
scope: AjaxConnectionManager
};
// Call webscript
AjaxConnectionManager.startRequest();
})();
//]]></script>
<#-- This closes the form.mode != "create" condition, so the js is only executed when in edit/create mode. -->
</#if>
I had a similar task before.
First you need to define a custom template in your configuration xml
<config evaluator="node-type" condition="my:type">
<forms>
<form>
<field-visibility>
<show id="cm:name" />
<show id="my:options" />
<show id="cm:created" />
<show id="cm:creator" />
<show id="cm:modified" />
<show id="cm:modifier" />
</field-visibility>
<appearance>
<field id="my:options">
<control template="/org/alfresco/components/form/controls/custom/custom-options.ftl" />
</field>
</appearance>
</form>
</forms>
</config>
What happens here is that the form engine will look for custom-options.ftl to render my:options for type my:type.
custom-options.ftl will contain the html needed to display your data and of course the call to javascript class that will load your list from your webscript.
So it looks like this
<#assign controlId = fieldHtmlId + "-cntrl">
<script type="text/javascript">//<![CDATA[
// Here you could call your webscript and load your list
</script>
<div id="${controlId}" class="form-field">
<label for="${fieldHtmlId}">${msg("form.control.my-options.label")}:<#if field.mandatory><span class="mandatory-indicator">${msg("form.required.fields.marker")}</span></#if></label>
<select id="${fieldHtmlId}" name="${field.name}" tabindex="0"
<#if field.description??>title="${field.description}"</#if>
<#if field.control.params.size??>size="${field.control.params.size}"</#if>
<#if field.control.params.styleClass??>class="${field.control.params.styleClass}"</#if>
<#if field.control.params.style??>style="${field.control.params.style}"</#if>>
</select>
<#formLib.renderFieldHelp field=field />
</div>
You can call webscript like this:
<script type="text/javascript">//<![CDATA[
var updateOptions = function(res){
var result = eval('(' + res.serverResponse.responseText + ')');
if(result.Options.length > 0 ) { // Options - returned JSON object
// do something with JSON data
}
}
Alfresco.util.Ajax.jsonGet({
url : Alfresco.constants.PROXY_URI + "/getOptions/{uniqueCode}"+ (new Date().getTime()),
successCallback : {
fn : updateOptions,
scope : this
},
failureCallback : {
fn : function() {},
scope : this
}
});
//]]></script>

Events not working when using Mustache with Backbone.js

So I am making a test app using RequireJs, Mustache and Backbone.js. I had some success with rendering the collection of models with the Mustache template. But my Mustache template has a button and when I try to bind click event on the button in the view, the button click doesn't invoke the callback function. I am really stuck, can someone tell me where I am not doing right?
Here is my code:
ItemView.js:
define(['jquery', 'backbone', 'underscore', 'mustache', '../../atm/model/item'], function ($, Backbone, _, Mustache, Item) {
var ItemView = Backbone.View.extend({
initialize: function() {
},
tagName: 'li',
events: {
'click .button': 'showPriceChange'
},
render: function() {
var template = $('#template-atm').html();
var itemObj = this.model.toJSON();
itemObj['cid'] = this.model.cid;
var rendering = Mustache.to_html(template, itemObj);
this.el = rendering;
return this;
},
showPriceChange: function(event) {
alert('Changing...');
$('#' + elemId).empty();
$('#' + elemId).append(document.createTextNode('Changed'));
},
});
return ItemView;
});
atm.html:
<!DOCTYPE html>
<html>
<head>
<title>Elevator</title>
<script data-main="scripts/main" src="scripts/require-jquery.js"></script>
<style type="text/css">
</style>
</head>
<body>
<h1>Vending Machine</h1>
<div id="atm-items">
</div>
<script id="template-atm" type="html/template">
<li>
<p>Item: {{name}}</p>
<label for="price-{{cid}}">Price:</label>
<input id="price-{{cid}}" type="text" value="{{price}}"/>
<button class="button">Change</button>
<p id="status-{{name}}-{{cid}}">- -</p>
</li>
</script>
</body>
</html>
You're replacing the view's el inside render:
render: function() {
//...
this.el = rendering;
//...
}
When you do that, you're losing the jQuery delegate that is attached to this.el, that delegate handler (which Backbone adds) is responsible for the event routing.
Usually, you add things to this.el rather than replacing this.el. If your template looked like this:
<script id="template-atm" type="html/template">
<p>Item: {{name}}</p>
<label for="price-{{cid}}">Price:</label>
<input id="price-{{cid}}" type="text" value="{{price}}"/>
<button class="button">Change</button>
<p id="status-{{name}}-{{cid}}">- -</p>
</script>
then you would this.$el.append(rendering) in your view's render; this would give you an <li> in this.el since you've set your view's tagName to li.
Alternatively, if you really need to keep the <li> in the template, you could use setElement to replace this.el, this.$el, and take care of the event delegation:
this.setElement(rendering);
Presumably you're wrapping all these <li>s in a <ul>, <ol>, or <menu> somewhere else; if you're not then you're producing invalid HTML and the browser might try to correct it for you, the corrections might cause you trouble elsewhere as your HTML structure might not be what your selectors think it is.

ajax not loading under external div

I have external html, where i have create the jcorousal (images are loading through ajax). but that external page is not loading in my current div:
<div class="corousal_content" id="MyDivName"> <!-- External html will load here--> </div>
This is my external page which consist jcarousal:
<script type="text/javascript">
alert("load ajax");
function mycarousel_itemLoadCallback(carousel, state)
{
// Since we get all URLs in one file, we simply add all items
// at once and set the size accordingly.
if (state != 'init')
return;
jQuery.get('dynamic_ajax.txt', function(data) {
mycarousel_itemAddCallback(carousel, carousel.first, carousel.last, data);
});
};
function mycarousel_itemAddCallback(carousel, first, last, data)
{
// Simply add all items at once and set the size accordingly.
var items = data.split('|');
for (i = 0; i < items.length; i++) {
carousel.add(i+1, mycarousel_getItemHTML(items[i]));
}
carousel.size(items.length);
};
/**
* Item html creation helper.
*/
function mycarousel_getItemHTML(url)
{
return '<img src="' + url + '" width="75" height="75" alt="" />';
};
jQuery(document).ready(function() {
jQuery('#mycarousel').jcarousel({
itemLoadCallback: mycarousel_itemLoadCallback
});
});
</script>
</head>
<body>
<div id="wrap">
<div id="mycarousel" class="jcarousel-skin-ie7">
<ul>
<!-- The content will be dynamically loaded in here -->
</ul>
</div>
</div>
please solve my problem.....
How do you load your external html?
Because, I think it failed to fire jQuery.ready event on external html.

ModalPopupExtender IFrame is blank in FireFox

I have implemented a modal popup using an IFrame. I use some javascript to hide the main content (Popup2_Panel1) and display a loading message (Popup2_Panel2) while the IFrame is loading. When the IFrame has finished loading (iframe's onload event) I hide the loading message and unhide the main content (with IFrame). This works in IE/Safari/Chrome/Opera, but in FF the IFrame content is blank after the main content is made visible.
How I can make this work in FireFox? If I leave out the hide/show code then the IFrame is visible in FireFox, but I don't really want to show the content before the iframe has loaded new content, otherwise we see the old content momentarily.
Here is my code:
<script type="text/javascript">
function ShowPopup(srcUrl, titleCaption, width, height) {
var frame = document.getElementById("Popup2_Frame");
// This code causes the IFrame to be blank in FireFox
document.getElementById("Popup2_Panel1").style.display = "none";
document.getElementById("Popup2_Panel2").style.display = "";
frame.width = width + "px";
frame.height = height + "px";
var title = document.getElementById('Popup2_Caption');
if (title) {
title.innerHTML = titleCaption;
}
frame.src = srcUrl;
var mpe = $find('Popup2_MPE');
if (mpe) {
mpe.show();
}
}
function PopupLoaded(frame) {
// This code causes the IFrame to be blank in FireFox
document.getElementById("Popup2_Panel1").style.display = "";
document.getElementById("Popup2_Panel2").style.display = "none";
var mpe = $find('Popup2_MPE');
if (mpe) {
mpe._layout();
}
}
</script>
<asp:ModalPopupExtender ID="ModalPopupExtender2" runat="server" TargetControlID="ImgButton13" PopupControlID="Popup2_Window" BackgroundCssClass="popupModalBackground" OkControlID="Popup2_OK" CancelControlID="Popup2_Cancel" Drag="True" PopupDragHandleControlID="Popup2_Titlebar" BehaviorID="Popup2_MPE">
</asp:ModalPopupExtender>
<div id="Popup2_Window" class="popupWindow" style="display: none;">
<div id="Popup2_Panel1">
<div id="Popup2_Titlebar" class="popupTitlebar">
<span id="Popup2_Caption">Caption</span>
<img id="Popup2_ImgClose" runat="server" style="float: right; cursor: pointer;" src="~/Masters/_default/img/delete.png" alt="Close" onclick="javascript:document.getElementById('MainContent_Popup2_Cancel').click()" />
</div>
<div class="popupContent">
<iframe id="Popup2_Frame" class="popupFrame" frameborder="0" onload="PopupLoaded(this)"></iframe>
</div>
<div class="tasks">
<Exhibitor:ImgButton ID="Popup2_OK" runat="server" CssClass="icon" Text="OK" ImgSrc="~/Masters/_default/img/action-yes.png" />
<Exhibitor:ImgButton ID="Popup2_Cancel" runat="server" CssClass="icon" Text="Cancel" ImgSrc="~/Masters/_default/img/action-no.png" />
</div>
</div>
<div id="Popup2_Panel2" class="popupLoading">
<center>
Loading...<br />
<br />
<asp:Image ID="Popup2_ImgLoading" runat="server" ImageUrl="~/Masters/_default/img/loading.gif" />
</center>
</div>
</div>
The solution is to use:
frame.style.visibility = "hidden";
...
frame.style.visibility = "visible";
instead of
frame.style.display = "none";
...
frame.style.display = "";
It appears FireFox will not display the IFRAME contents at all after setting display="none" and then trying to set display="", even though it appears to be loading the URL in the background. If we set visibility to hidden the element is hidden but still takes up space so we have to do some additional juggling to give it a zero size while loading.

Resources