Here is function that creates javascript objects
public IEnumerable<ScriptDescriptor>
GetScriptDescriptors()
{
ScriptControlDescriptor descriptor = new ScriptControlDescriptor("HierarchyPathControl.PathExplorer", this.ClientID);
descriptor.AddProperty("some_property", "some_value");
yield return descriptor;
}
Here is part of .js file
Type.registerNamespace("HierarchyPathControl");
HierarchyPathControl.PathExplorer = function (element) {
HierarchyPathControl.PathExplorer.initializeBase(this, [element]);
alert("invoked");
}
HierarchyPathControl.PathExplorer.prototype = {
initialize: function () {
HierarchyPathControl.PathExplorer.callBaseMethod(this, 'initialize');
alert("not invoked");
},
..............................
Why second alert invokes only if I remove this line:
descriptor.AddProperty("some_property", "some_value");
Thanks.
Check the error console if you have js error during page initialization. The problem seems to be that you didn't define some_property property in you client side class.
Ensure that you have the following definition of the get/set methods inside your HierarchyPathControl.PathExplorer client side class:
get_some_property = function() {
return this._some_property;
},
set_some_property = function(value) {
if (this._some_property != value) {
this._some_property = value;
this.raisePropertyChanged('some_property');
}
}
Here basically some_property should be the name of the property you want to create.
Related
I'm converting some of our application from JavaScript to TypeScript, and have a JavaScript method that execute functions via the window element by the function name.
We are having trouble finding and executing the correct function from the TypeScript produced JavaScript.
TypeScript Code:
class ItemSelector {
public static preProcesssData(data: any): any {
//Do Stuff
return data;
}}
Produced JavaScript
var ItemSelector = (function () {
function ItemSelector() {
}
ItemSelector.preProcesssData = function (data) {
//Do Stuff
return data;
};
return ItemSelector;}());
JavaScript Calling Function
function callFunctionByName(funcName,data) {
var fn = null;
/*
* If function has a scope (namespace) like this: "myScope.myFunction"
*/
if (funcName.indexOf(".") != -1) {
var ns = funcName.split(".");
if (ns && ns.length == 2) {
fn = window[ns[0]][ns[1]];
} else {
cl("Function with multiple scopes not supported: " + funcName);
}
}
/*
* Else function is just a plain string with no scope.
*/
else {
fn = window[funcName];
}
//fn is always undefined
if (typeof fn === "function") { fn(data);}}
Example Call
callFunctionByName("ItemSelector.preProcessData",{});
window["ItemSelector"]["preProcessData"] returns undefined.
window["Itemselector.preProcessData"] also returns undefined.
I'm sure this is a very easy one, but I just can't figure it out.
Thanks, Matt
You've spelled Process as Processs in your class.
In the following code, .refresh could call .add, but I get Uncaught TypeError: undefined is not a function
My guess is because it is not defined at the time class is created, but if this is true, without replicating the code, is there a way to call a sibling public function from the same class?
var fileSelector = (function () {
var self = this;
function callback (data,status,xhr) {
$("#File_Selector_Container").html(data);
utils.setItem ("fileSelector", "TRUE");
}
return {
refresh : function () {
if (utils.getItem ("fileSelector") == "TRUE") {
self.add();
}
},
add : function () {
$.get(script_name ,"AddFileSelector",callback,"html");
},
remove : function () {
$("#File_Selector_Container").html("");
}
}
})();
I started this from: Simplest/Cleanest way to implement singleton in JavaScript? and I can't find it now, but another question where I got self=this from.
this (and hence self) simply refers to the global object (i.e. window). That's why you get the error, there is no global add function. I recommend to read the MDN documentation to learn how this works.
One solution is to keep a reference to the object you are returning and use that instead:
var fileSelector = (function () {
function callback (data,status,xhr) {
$("#File_Selector_Container").html(data);
utils.setItem ("fileSelector", "TRUE");
}
var fileSelector = {
refresh : function () {
if (utils.getItem ("fileSelector") == "TRUE") {
fileSelector.add();
}
},
add : function () {
$.get(script_name ,"AddFileSelector",callback,"html");
},
remove : function () {
$("#File_Selector_Container").html("");
}
};
return fileSelector;
})();
Given that I have a class defined such as
(function () {
function Dummy(){
var toReturn ={
myProp : "asdf",
myFunc : myFunc
}
return toReturn;
function myFunc(){};
}
})();
how does one get an instance of the same type after
var dummy = new Dummy();
JSON.stringify(dummy);
so that I have myFunc still available on the type.
JSON.parse(JSON.stringify(dummy)) returns same shape of the object by not the same type.
NOTE: I am not asking about capability of JSON, but how do people deal with this in general. Do you hand roll your mapping mechanism so that after parsing from JSON you map it onto instance of the type, or if there is such functionality in some library, such as underscore.
I created a helper function that helps me do this, but would like to hear from others how do you deal with situation like this. As I put in comments, JSON comes over the wire, for which we have a type defined. To get the values from JSON in our type, we parse json, create instance of type and then apply map function below.
function map(fromObj, toObj) {
Object.keys(fromObj)
.forEach(function (key) {
if (typeof fromObj[key] != 'function') {
if (toObj.hasOwnProperty(key)) {
if (typeof fromObj[key] !== 'object') {
toObj[key] = fromObj[key];
} else {
map(fromObj[key], toObj[key]);
}
}
}
}
});
}
Note, Not certain about requirement , if this similar to what posed at Question. If off-topic , please post comment , will withdraw.
Piece was originally composed for this Question Organizing large javascript files [on hold] . With a json response , having "x" type of contents , could map returned object to new object , copying properties utilizing $.extend() .
Result would be new object having both properties and functions of returned data. At piece below, at completion of process , $.Pages begins as function , then type gets converted to object - though it could retain both function and object properties by including || {} at definition stage.
Functions within returned json objects could be called within .then() callback ; see console at jsfiddle , object init functions.
At conclusion , $.Pages object has properties of returned json , including access to functions . Based on a jsonp - type processing flow.
Piece is "frame" of a processing approach ; could extend to include other functionality
$(function() {
var dfd = new $.Deferred();
dfd.progress(function(msg) {
console.log(msg);
});
ProductPage = {
name : "ProductPage",
addToCartBtn: "#add-to-cart",
initName : function() {return dfd.notify(this.name)},
init: function() {
this.initName();
// ProductPage.initAddToCartPopup();
// ProductPage.initSidebar();
}
};
ContactPage = {
name : "ContactPage",
validateEmail : function (e) {return dfd.notify(e)},
initName : function() {return dfd.notify(this.name)},
init: function() {
this.initName();
// ProductPage.initAddToCartPopup();
// ProductPage.initSidebar();
}
};
var mods = function() {
return {"ContactPage" : ContactPage
, "ProductPage" : ProductPage };
};
$.Pages = function() {
$.when(mods())
.done(function(pages) {
$.Pages = pages;
});
return $.Pages
};
$.when($.Pages())
.then(function() {
$.each($.Pages, function(k, v) {
v.init();
})
});
console.log($.Pages)
});
jsfiddle http://jsfiddle.net/guest271314/60kv2439/1/ (see console)
basic approach
$p = {};
var queue = [];
var mods = ["dep1.json", "service1.json"];
var mod = function(m) {
queue.push(m);
if (queue.length === mods.length) {
$.each(queue, function(k, v) {
$p = $.extend(v, $p)
})
}
};
$.each(mods, function(k, v) {
$.getScript(v, function(script, status, jqxhr) {
console.log($p)
})
})
I'm writing a jQuery plugin to allow the initializing of multiple, single file upload fields (using Fine Uploader) in a specified form.
Ultimately I would like the form to know that it has these single uploaders attached to it, so I can run some validations, etc before manually starting the file uploads and submitting the form.
My ideal initialization code would look like this:
var form = $("form");
form.uploader();
form.addUploader({
element: '.uploader_one'
});
form.addUploader({
element: '.uploader_two'
});
So far the plugin I wrote to make this happen looks like:
(function($) {
var Uploader = function(form){
addUploader = function() {
// Initialize Fine Uploader
}
$(form).submit(function(e) {
// Run validations, then process uploaders
$(this).submit();
}
}
$.fn.uploader = function(options) {
var uploader = new Uploader(this);
};
})(jQuery);
Most of this works, except that the addUploader function is not publicly accessible.
Might I be going about this the wrong way? Any help would be much appreciated!
You would need to make the addUploader a member of the object to make it accessible through the object (instead of as a global variable disconnected from the object):
this.addUploader = function() {
The plugin has to do something with the object so that it becomes accessible, for expample returning it:
$.fn.uploader = function(options) {
return new Uploader(this);
};
Now you can get the object from the plugin and use it:
var form = $("form");
var upl = form.uploader();
upl.addUploader({
element: '.uploader_one'
});
upl.addUploader({
element: '.uploader_two'
});
You should follow the general practice for developing plugins. A suggested structure for your plugin is something like:
(function($) {
var methods = {
init: function (options) {
var data = $(this).data("uploader-plugin");
if (!data) {
$(this).on("submit", function (e) {
});
$(this).data("uploader-plugin", new Uploader(options));
}
},
add: function (options) {
// Use `options.element`
$(this).data("uploader-plugin").elements.push(options.element);
console.log($(this).data("uploader-plugin"));
}
};
var Uploader = function (opts) {
this.whatever = opts.a;
this.elements = [];
};
$.fn.uploader = function(method) {
var args = arguments;
return this.each(function () {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(args, 1));
} else if (typeof method === "object" || !method) {
return methods.init.apply(this, args);
} else {
$.error("Method " + method + " does not exist on jQuery.uploader");
}
});
};
})(jQuery);
DEMO: http://jsfiddle.net/WyGqc/
And you will call it like this:
var form = $("form");
form.uploader({
a: "whatever";
});
form.uploader("add", {
element: ".uploader_one"
});
It actually applies it to all selected elements from the original selector, and continues chaining. It also follows the normal convention for plugin use - meaning, you call the plugin name (uploader) with different parameters to do different things.
I have a problem with the value assignment and retrieval in asp.net ajax. The value of timestamp is undefined
Code:
/// <reference name="MicrosoftAjax.js"/>
Type.registerNamespace("LabelTimeExtender1");
LabelTimeExtender1.ClientBehavior1 = function(element) {
LabelTimeExtender1.ClientBehavior1.initializeBase(this, [element]);
this._testelement=this.get_element();
this._timestamp= this.get_element().attributes['TimeStamp'].value;
alert(_timestamp);
},
LabelTimeExtender1.ClientBehavior1.prototype = {
initialize: function() {
LabelTimeExtender1.ClientBehavior1.callBaseMethod(this, 'initialize');
setInterval (this.timer,1000);
alert("after");
},
dispose: function() {
//Add custom dispose actions here
LabelTimeExtender1.ClientBehavior1.callBaseMethod(this, 'dispose');
},
timer: function(){
alert(this.timestamp);
var splitdate=this._timestamp.split(/[:]+/);
alert(splitdate);
var date= new Date(this._timestamp);
alert( date.toString());
var datenow= new Date ();
alert(datenow.toString());
this._element.innerText=" ";
alert(this._element);
if(date.getUTCFullYear<datenow.getUTCFullYear)
{
alert("year");
var myelement= this.get_element();
myelement .innerHTML= date.getUTCFullYear.toString();
}
if(date.getUTCMonth<datenow.getUTCMonth)
{
alert("month");
this.get_element().innerHTML=date.getUTCMonth.toString();
}
if(date.getUTCDay<datenow.getUTCDay)
{
this.get_element().innerHTML=date.getUTCDay.toString();
}
if(date.getUTCHours <datenow.getUTCHours )
{
this.get_element().innerHTML=date.getUTCHours .toString();
}
if(date.getUTCMinutes<datenow.getUTCMinutes)
{
this.get_element().innerHTML=date.getUTCMinutes.toString();
}
},
set_timestamp: function(value)
{
this._timestamp=value;
},
get_timestamp: function()
{
return this._timestamp;
}
}
LabelTimeExtender1.ClientBehavior1.registerClass('LabelTimeExtender1.ClientBehavior1', Sys.UI.Behavior);
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
Why is the value of _timestamp undefined?
I would suggest moving the code which sets this._timestamp into your initialize function.
My other suggestion is to use the getters and setters even within your own code to ensure encapsulation. So, the alerts would actually be alert(this.get_timestamp()). And, in your initialize function, you would call this.set_timestamp(this.get_element().attributes['TimeStamp'].value).
Thanks to the comment I see the problem is actually in the setInterval call. When you call window.setInterval(this.timer, 1000);, when the timer function is called this refers to window, not to your object. So instead, do something like this:
var self = this;
window.setInterval(function () {
self.timer();
}, 1000);
That will make this inside of timer() refer to the correct object.