I am using the LiveValidation plugin and was wondering of there is a way to add HTML in the span tags that show a valid or invalid message. I have the following:
var validatedObj = new LiveValidation('momlastname', { validMessage: ""});
validatedObj.add(Validate.Presence,{ failureMessage: "You need a name in this <strong>field</strong>"});
But when I test the code I get this:
Imgur
What am I missing?
It is not implemented, failureMessage parameter is treated as string. Here is function that creates message ( source ), so you can change that:
createMessageSpan: function(){
var span = document.createElement('span');
var textNode = document.createTextNode(this.message);
span.appendChild(textNode);
return span;
},
It is also possible to override onValid and onInvalid default callbacks, and to impliment your own functionality. Check the official documentation for more info.
Thanks #Danijel. I modified the function as follows:
createMessageSpan: function () {
var span = document.createElement('span');
span.innerHTML = this.message;
return span;
},
Related
I'm using the 'Compilation.xml' template from the TVMLCatalog
I'd like to add a button click event to a 'listItemLockup'
<listItemLockup>
<ordinal minLength="2" class="ordinalLayout">0</ordinal>
<title>Intro</title>
<subtitle>00</subtitle>
<decorationLabel>(3:42)</decorationLabel>
</listItemLockup>
I've tried adding:
App.onLaunch = function(options) {
var templateURL = 'http://localhost:8000/hello.tvml';
var doc = getDocument(templateURL);
//doc.addEventListener("select", function() { alert("CLICK!") }, false);
var listItemLockupElement = doc.getElementsByTagName("listItemLockup");
listItemLockupElement.addEventListener("select", function() { alert("CLICK!") }, false);
}
addEventListener
void addEventListener (in String type, in Object listener, in optional Object extraInfo)
Is "select" the correct type?
I've been using the following tutorials
http://jamesonquave.com/blog/developing-tvos-apps-for-apple-tv-with-swift/
http://jamesonquave.com/blog/developing-tvos-apps-for-apple-tv-part-2/
Update
I'm getting an error
ITML <Error>: doc.getElementsByTagName is not a function. (In 'doc.getElementsByTagName("listItemLockup")', 'doc.getElementsByTagName' is undefined) - http://localhost:8000/main.js - line:27:58
I tried adding this to the 'onLaunch'
var listItemLockupElements = doc.getElementsByTagName("listItemLockup");
for (var i = 0; i < listItemLockupElements.length; i++) {
//var ele = listItemLockupElements[i].firstChild.nodeValue;
listItemLockupElements[i].addEventListener("select", function() { alert("CLICK!") }, false);
}
I'll see about the error first
Cross Post: https://forums.developer.apple.com/thread/17859
More common example I have seen by Apple is to define a single overall listener like:
doc.addEventListener("select", Presenter.load.bind(Presenter));
In your xml, assign unique ids to elements, or give them ways to identify them.
For example, the beginning would be something like:
load: function(event) {
var self = this,
ele = event.target,
attr_id = ele.getAttribute("id"),
audioURL = ele.getAttribute("audioURL"),
videoURL = ele.getAttribute("videoURL")
And then you can do whatever you want with your item.
if(audioURL && (event.type === "select" || event.type === "play")) {
//
}
My advice would be to study the Presenter.js file more carefully for this pattern.
Edit:
Answering your "Update" related to doc.getElementsByTagName is not a function. "doc" does not actually exist, but the general pattern is to get it with
var doc = getActiveDocument();
I assumed you would know the above.
Does that fix it?
var listItemLockupElement = doc.getElementsByTagName("listItemLockup”);
In this case, the listItemLockupElement is a NodeList, not an element. You can either iterate through the list and add an event listener to each listItemLockup, or you could add the event listener to the containing element.
When addressing items in a NodeList, you use the item(i) method rather than the standard array access notation:
listItemLockupElements.item(i).addEventListener("select", function() { })
See: https://developer.mozilla.org/en-US/docs/Web/API/NodeList/item
Adding event listeners is straightforward if you're using atvjs framework.
ATV.Page.create({
name: 'mypage',
template: your_template_function,
data: your_data,
events: {
select: 'onSelect',
},
// method invoked in the scope of the current object and
// 'this' will be bound to the object at runtime
// so you can easily access methods and properties and even modify them at runtime
onSelect: function(e) {
let element = e.target;
let elementType = element.nodeName.toLowerCase();
if (elementType === 'listitemlockup') {
this.doSomething();
}
},
doSomething: function() {
// some awesome action
}
});
ATV.Navigation.navigate('mypage');
Disclaimer: I am the creator and maintainer of atvjs and as of writing this answer, it is the only JavaScript framework available for Apple TV development using TVML and TVJS. Hence I could provide references only from this framework. The answer should not be mistaken as a biased opinion.
I'm working with html service of google-apps-script and I'm writing some modules to make life easier. The module below its designed to create elements fast and easy with an easy to read notation.
All works fine except the text function. It uses the input function to create a specific input type. In this case, a text one. When I try to use it I get the following error:
Untaming of guest constructed objects unsupported
I can't understand this error. Could anyone explain it to me?
var util = {
create: (function(){
var element = function (elementName,atributes ){
var element = $( document.createElement(elementName) );
return atributes ? element.attr(atributes) : element;
},
div = function(atributes){ return element('div',atributes); },
textArea = function(atributes){ return element('textarea',atributes); },
input = function(atributes){ return element('input',atributes); },
text = function(atributes){
atributes.type = "text";
return input(atributes);
};
return { div:div, input : input, text:text, textArea:textArea}
})()
};
I have a variable
var qstAccessCode:String = "default";
and a loader with URLRequest
var qst:XML;
var qstLoader:URLLoader = new URLLoader();
qstLoader.load(new URLRequest("http://dl.dropbox.com/u/44181313/Qaaps/Audio/" + qstAccessCode + ".qst"));
qstLoader.addEventListener(Event.COMPLETE, processQST);
function processQST(e:Event):void {
qst = new XML(e.target.data);
trace("QST loading");
}
I would like to use the value of qstAccessCode to complete the URL (so I can change the URL based on user input - if no input then use "default") but I get an error:
"1120: Access of undefined property qstAccessCode"
Is this to do with scoping? How can I complete the URL? Thanks in advance.
Edit: I haven't been able to get clear on this, so I'm also going to look at generating the complete URL from the user-input function and see if I get the URLRequest to pick it up as a variable. If there are any further comments on the original idea I will be very grateful to read them. Cheers.
Edit: #Moorthy I have qstAccessCode defined like this:
var qatAccessCode:String = "default";
var stageText:StageText = new StageText();
stageText.returnKeyLabel = ReturnKeyLabel.GO;
stageText.stage = this.stage;
stageText.viewPort = new Rectangle(225, 765, 200, 35 );
stageText.addEventListener(Event.CHANGE, onChange);
function onChange(e:Event):void
{
qatAccessCode = stageText.text;
trace(qatAccessCode);
}
It traces keyboard entry when I test movie (Air 3.2 for Android).
qstAccessCode should be defined in the same scope as the URLRequest.
You must defined property qstAccessCode like:
var qstAccessCode:string;
qstAccessCode's value is your url address.
Can anyone confirm that HTML widgets accept ClickHandlers on the Server side ? I can't get my below code to work.
I create a serverHandler (and for good measure I have even added a useless callback element). Subsequently, I add it to a HTML.addClickHander (for good measure I have even added it to .addMouseUpHandler as well). The function is NOT executed.
var mouseclick = app.createServerHandler("handleTrainingClick_").addCallbackElement(lstFilter);
var params = [ "fromOrg", "trainingTitle", "dueDate", "medical", "status" ];
var resultSet = blSelectActiveTrainings_();
while (resultSet.hasNext()) {
var training = resultSet.next();
var html = TRAINING_ROW;
for (var pI in params) {
html = html.replace("$"+params[pI], training[params[pI]]);
}
pnlList.add(app.createHTML(html).setId(training.id).addClickHandler(mouseclick).addMouseUpHandler(mouseclick)
.addMouseMoveHandler(mousemove).addMouseOutHandler(mouseout).addMouseOverHandler(mouseover));
}
function handleTrainingClick_(e) {
Logger.log(e.source);
var app = UiApp.getActiveApplication();
return app;
}
HTML widgets server side handlers work just fine. It was an incorrect reference in my code. Thanks all.
I'm using the mootools wall plugin, Its working well in my application, however if I add multiple (image) walls it only works for one wall ::: My understanding of scripting is not good enough to add a each function or similar :::
I need to "bind" the code below to say 2 divs like this :::
My First wall:
<div id="viewport">
<div id="wall">
Second wall:
<div id="viewport">
<div id="wall_02">
Any assistance would be appreciated.
var wallIMAGES = new Wall( "wall", {
"width": scArray[1],
"height": scArray[1],
callOnUpdate: function(items){
items.each(function(e, i){
var el = wall[counterFluid];
if (el) {
var a = new Element("img[width="+scArray[1]+"][height="+scArray[1]+"][src={thumb}]".substitute(el));
a.inject(e.node).set("opacity", 0).fade("in");
e.node.store("tubeObject", el);
}
counterFluid++;
// Reset counter
if( counterFluid >= scArray[10].length) counterFluid = 0;
})
}
});
wallIMAGES.initWall();
Maybe something like this:
var my_wall_ids = ['wall', 'wall_02'];
var myWalls = [];
var baseWallOptions = {
"width": scArray[1],
"height": scArray[1],
callOnUpdate: function(items){
items.each(function(e, i){
var el = wall[counterFluid];
if (el) {
var a = new Element("img[width="+scArray[1]+"][height="+scArray[1]+"][src={thumb}]".substitute(el));
a.inject(e.node).set("opacity", 0).fade("in");
e.node.store("tubeObject", el);
}
counterFluid++;
// Reset counter
if( counterFluid >= scArray[10].length) {counterFluid = 0;}
}); // end items.each
}
}
for (var i=0;i<my_wall_ids.length;i++){
var id = my_wall_ids[i];
var wallOptions = baseWallOptions;
// if your customization was something like changing
// the height , but only on the 'wall' element
if (id === 'wall') {
wallOptions.height = 400;
}
myWalls[i] = new Wall(id, wallOptions);
myWalls[i].initWall();
}
If you read Wall's documentation, you'll notice that, just like most other classes, the first argument it takes is an element id.
So, if your initialization code states
new Wall("wall", { …
…then it will be applied to the element that has the id "wall".
You could simply duplicate your code and use one with "wall", the other one with "wall_02". However, that would be bad practice. Indeed, if you later wanted to change some options, you'd have to do it in two distinct blocks, and they would probably get out of sync.
If your only difference lies in the target id, and the options are to be shared, simply store the options object (second parameter to the Wall class) in a variable and use it twice! That is:
var wallOptions = { width: … };
var wallImages = new Wall("wall", wallOptions),
wallImages2 = new Wall("wall_02", wallOptions);
wallImages.initWall();
wallImages2.initWall();
It could be even better to embed initalization in a function, but this solution is probably the easiest if you simply want to have two Wall instances without learning much more about JS.