Appcelerator titanium - passing js variables - javascript

I am new to JS and Appcelerator titanium. I am trying to implement the MVC model to my app, but I have a problem accessing the data in the model:
in the model.js:
var my_val;
then in file1.js, I modified the value of my_val:
Ti.include("model.js");
my_val=5;
then in another file file2.js:
Ti.include("model.js");
T.API.info(my_val); // the value I always get is "undefined"
why is file2.js not detecting the change file1.js has done to my_val? Is there anyway to make it work?

take a look at my blog posting regarding this particular problem.
blog.clearlyinnovative.com
you want to include both files in your app.js and add the variable to your namespace; this is cleaner and doesn't pollute the global scope.
var myApp = {};
Ti.include("model.js");
Ti.include("file2.js");
in model.js do something like this
var myApp.model = {};
myApp.model.my_val = 100;
in file2.js do something like this; no need to incude model.js again, the value was set in your own namespace and is clearly defined
Ti.API.info(myApp.model.my_val);

If you want to get this functionality done use Titanium Properties so that you can get/set your variable as per requirement.Do something like this in your app.js
// initialize your variable, you can update it as well with your custom value
Titanium.App.Properties.setInt('my_value', 0);
You can get this value any where you want like this:
var myValue = Titanium.App.Properties.getInt('my_value');

This is because what the statement
Ti.include('model.js');
does is to just sort of 'copy-paste' the code in your 'model.js' file into the other two files. All the variables in 'model.js' will be available to the file in which you included 'model.js'. But this only means that a copy of the variable my_val is made available to 'file2.js' not a variable that is common to all files that have the Ti.include('model.js') line!Including a file in another is pretty much the same as typing out the lines of the first file into the second but it in no way connects all files that include a common file!
So maybe instead of
Ti.include('model.js');
Ti.API.info(my_val);
you can this try this seeing as you have already included 'model.js' in 'file1.js??'
Ti.include('file1.js');
Ti.API.info(my_val);
OR you can always go with Muhammad Zeeshan's advice and check out Ti.App.Properties. Good Luck! :)

Related

How to access c# variables from a JavaScript file?

I have a C# file that pulls various config settings from different config files. A JavaScript application I'm writing needs some of those settings to run. I'm having trouble bringing the C# variables into the js file. Not sure what is the best approach. They need to end up as a JS object on the page. Would adding them to a JSon object in the C# file & calling that from the JS file work? Not even sure how to do that to be honest. Any help appreciated.
You can just declare a global variable in one of your root pages (say, _layout.cshtml):
<script>
var settings = {
foo: #(IsFoo ? "true", "false"),
bar: #SomeNumber,
baz: "#ImportantString"
}
</script>
Or, if you're writing a Web API, you can just add a /settings endpoint you can query like so (Assuming you're using jQuery):
$.get("/settings", response => {
// Store the `response` in a global variable.
});
If it's an independent javascript project and .net is more of an API, you need to make an API call which will send you those config settings.
If your javascript is part of .net MVC application, i.e., you are adding your javascript through an tag at then end of a .cshtml/.aspx file, you can easily pass it through a global variable, but even then the C# code need to pass those values through Modal to the .cshtml/aspx file.
what you can do is:
var pageConfig = pageConfig || {};
pageconfig.settings = #Html.Raw(Model.Settings); // This model object is part of the C# code and my assumption is that Settings will have array of configurations.
This can also be done globally, depending upon how the C# code is written.
Assuming that when you say 'various config settings' you're referring to .NET's ApplicationSettings (defined in Visual Studio's Properties > Settings), we've done something similar, in a generic manner, as follows:
public void WriteSettings(TextWriter writer)
{
// Declare the nameSpace for the DLL you want to pull settings from
var nameSpace = "foo.Bar"
ApplicationSettingsBase properties = (System.Configuration.ApplicationSettingsBase)Activator.CreateInstance(nameSpace, string.Format("{0}.Properties.Settings", nameSpace)).Unwrap();
foreach (SettingsProperty property in properties.Properties)
{
writer.Write(string.Format("{0}=\"{1}\", property.Name, properties[property.Name]);
}
}
I've ignored a few issues in your case:
I've not bothered trying to deal with non-strings; consider looking at property.PropertyType and casting your values appropriately
I've wrapped this in a function that accepts a TextWriter; you can pass this method Response.Output

Access variable from 1 .js source file (jqTree), from within different .js file, to override method

(new to JS, jQuery, & jqTree)
I am trying to override a method (JqTreeWidget.prototype.openNode) from one .js file (tree.jquery.js) in another (my own custom.js).
I've read that to override a js method in general, I just need to redefine it. So I am trying to do that on the method, and I think I am stuck on accessing the variable that has the original method (JqTreeWidget). I think the challenge is that the original method is in tree.jquery.js (source) that is separate from my own other custom.js file where I want to do the override.
The goal of this Question would be to allow me to write something like this in my custom.js (<reference to JqTreeWidget.prototype.openNode> would be the Answer to this Question):
var originalMethod = <reference to JqTreeWidget.prototype.openNode>;
// Override of originalMethod
<reference to JqTreeWidget.prototype.openNode> = function( node, slide ){
// my code I want to happen 1st here
changeAncestorHeightRecursively( node, true);
// my code is done, and now I'm ready to call the original method
originalMethod.call( this, node, slide );
}
I think that would be the most non-intrusive way to do the override, without actually hacking in to the tree.jquery.js source.
See my custom.js at http://codepen.io/cellepo/pen/LGoaQx
The separate source tree.jquery.js is added externally in the JS settings of that codepen.
How can I get access (from within my custom.js file) to JqTreeWidget variable that is in the source file (tree.jquery.js)? Is it even possible? Is JqTreeWidget not in scope outside of tree.jquery.js, or is it not a global variable? I was hoping treeContainer.tree.prototype would have it, but I haven't had luck so far...
Thanks!
The prototype object can be obtained via:
jQuery.fn.tree("get_widget_class").prototype
Note that this is not a generalized solution for any jQuery plugin. This is something explicitly implemented by the tree plugin.
I found this hacky workaround. But since it's a hack, I'd still prefer to find the Answer as posed in this Question (so please, continue to Answer with respect to the <reference to JqTreeWidget.prototype.openNode> I mentioned in the Question, thanks)...
As stated in this Question, the goal involves making it possible to override JqTreeWidget.prototype.openNode (from tree.jquery.js) externally in custom.js. As such, calls to changeAncestorHeightRecursively (my code) & JqTreeWidget.prototype.openNode would both be made from the override in custom.js, and tree.jquery.js source is not modified at all.
Workaround:
Declare global var in html:
<script type='text/javascript' language="javascript">
changeAncestorHeightRecursively = 1;
</script>
In custom.js, set the globar var to the function (the one I want to be called before JqTreeWidget.prototype.openNode):
window.changeAncestorHeightRecursively = changeAncestorHeightRecursively;
Call the global-var-referenced function at the beginning of JqTreeWidget.prototype.openNode (hack into tree.jquery.js):
JqTreeWidget.prototype.openNode = function(node, slide) {
// Only way I could figure out to get this to execute before the rest of this method
// (global-var-referenced function in custom.js)
changeAncestorHeightRecursively( node, true );
// Rest of original openNode code...
}
This calls my code function from within tree.jquery.js, as opposed to calling the overridden method from within custom.js. So this is hacky because of the global var, and modifying tree.jquery.js source.
This will work for now, but hoping for a less hacky Solution as stated in this original Question... Thanks!

How do I get my helper functions to load first? (Meteor, Node framework)

In my Meteor projects I have several helper functions of the sort
helpers.js
var tagStr = function () { return this.tags.join(', '); };
articles.js
Template.articles.tags = tagStr;
listing.js
Template.listing.tags = tagStr;
Now, I can define the function in either articles.js or listing.js, and it won't work in the other one. Or i can define it in helpers.js and it will work in neither..
So, how would I go about loading my helper functions before the rest of the scripts? Preferably in "the right way".
Thanks!
i think what you are looking for is a globally available handlebars helper - i keep mine in client/lib/handlebars.js - the contents of the 'lib' folder will get loaded first
define each helper like so:
Handlebars.registerHelper("joinArray", function(array) {
if(array)
return array.join(', ');
});
you would then use this in any template html file like so:
{{joinArray tags}}
you can read more about handlebars helpers here handlebarsjs.com/block_helpers.html
this is the 'right' way IMO, but if you want to use normal javascript functions and not handlebars helpers, that works also
you'll need to place the commonly used javascript function in a file like client/lib/helpers.js and do NOT use the 'var' declaration prefix
like so:
thisIsAGloballyAvailableFunction = function(){...};
not like:
var thisFunctionIsOnlyAvailableInThisFile = function(){...};
meteor does a slightly strange thing to control scoping. anything with 'var' is local to the scope of the file it occurs in, anything declared without 'var' is globally available across the app
The answer by nate-strauser was correct and helped me find the right solution but now (Meteor 1.0) Handlebars.registerhelper() is deprecated.
Now it works this way (if anyone is still interested):
Template.registerHelper()
The rest as explained by nate-strauser.

Titanium, calling a function in one JS file from another JS file

so i have been trying for many hours a day now for the past 3 days.i researched this to death but still cannot get it.
Goal:
-file1.js has a buttion that when pressed will call method Main_Menu in file2.js and will open a new window created by that method, or function.
failed attempts:
-i have tried Ti.include but always getting a, cant find file error, i have tried changing string to every possible path.
-var file = require(path) but can not use the method inside the file, for example file.Main_Meue, does not work
I have also tried many other things that do not come to mind but if anyone has any advice or you need more information just ask. PLEASE HELP, AND THANKYOU
second answer
Create the second window like so:
//file1.js
button.addEventListener('click', function()
{
var secondWindow = Ti.UI.createWindow({
url:'file2.js'
});
secondWindow.open();
});
file1.js creates a new window using file2.js via the url parameter. file2.js is now your new window after calling secondWindow.open()
First answer
Based off the title of this topic, you can use the fireEvent method. For example:
file1.js
Ti.App.addEventListener('customEventName', function()
{
Ti.API.info('function fired from file2.js');
});
file2.js
Ti.App.fireEvent('customEventName');
http://docs.appcelerator.com/titanium/latest/#!/api/Titanium.Proxy-method-fireEvent
file1.js
var toBeExported ={
a : function(){
//your code goes here
}
};
exports.a = toBeExported.a
file2.js
var b = require ('file1');
//you can use all the functions that is exported from file1 here.
//you have to create a lib folder or place the file1.js in the existing lib folder for the export/require to work.
Hope this will help.
this might be a problem of code structure. Basically you have three good way to doing this depending on which version you are using (actually on which version you started your project :
before 2.x : the best way was call the tweetanium architecture : www.shanestillwell.com/index.php/2012/03/29/mvc-for-appcelerator-titanium-understanding-tweetanium/
for 2.x : you can use the CommonJS structure : https://wiki.appcelerator.org/display/guides/CommonJS+Modules+in+Titanium
for 3.x : you should take a look at the Alloy.Globals which is the almost the same than tweetanium
Hope it helps.

send data to JS file without using global variables

I need to send data in a HTML page to a script file that is loaded in that page. The simplest way i can think of is to use a global variable which is defined in the page and accessed in the script file.
We all know global state is bad, so i started thinking about the options available for passing data from HTML page to script file without using global state. I cant find (or think of) any.
I am curious whether this is possible. Any ideas?
It really depends what you're doing. In general, I wouldn't advise this methodology, but it's something to consider depending on your circumstances. For the sake of this example, I'll assume you're using jQuery (if not, replace the document.ready with whatever you want to use for onDOMReadyStateChange monitoring).
In the HTML:
<script type='text/json-data' id='some_data_set'>
{ 'foo': 'bar', 'baz': 1 }
</script>
In the JavaScript:
$(function() {
var myData = JSON.parse($('script#some_data_set').html());
// YOUR CODE GOES HERE
});
Nope. All the javascript scope starts from a global level, therefore you must have at least one global reference to your data.
Let's say you wanted to store a list of products and events:
var myGlobalData = { "products":<products>, "events":<events> };
Where <products> and <events> are two different data blocks.
If you're paranoid on global objects, you can simply delete the reference point (thus it's contents) after you finished using it, as follows:
delete window.myGlobalData;
One option is to scope your data. For example, in JS file you can define an object like:
var processor = {
function setData(o) { // do stuff
}
};
Then in your HTML you know that the data is scoped to the processor. So you can do something like:
processor.setData({someData});

Categories