I have a jQuery plugin in my layout page header:
<script src="#Url.Content("~/Scripts/js/kendo.web.min.js")"></script>
<script src="#Url.Content("~/Scripts/app/jsCommon.js")"></script>
<script src="#Url.Content("~/Scripts/app/Layout.js")"></script>
and my layout.js:
(function ($) {
var Layout = function (node, options) {
this.node = node;
this.options = $.extend({
url: ""
}, options);
$(this.node).find('.HButton').bind('click', $.proxy(this.HButtonClicked, this));
};
Layout.prototype = {
constructor: Layout,
_loadBackground: function () {
debugger;
//load second now 'Common.currentTarget' have been lost
$(Common.currentTarget).removeClass();
$(Common.currentTarget).addClass(".HButton_Selected");
},
HButtonClicked: function (e) {
debugger;
//load first
Common.currentTarget = e.currentTarget;
}
}
$.fn.Layout = function (options) {
return this.each(function () {
$(this).data('Layout', new Layout(this, options));
});
};
}(jQuery));
in the other side I have a share repository javascript object like this :
function common() {
}
common.currentTarget = null;
var Common = new common();
then in the other page I've triggered an event like following :
<script>
$(document).ready(function () {
var layout = $("#layout").data("Layout");
$(layout).trigger("_loadBackground")
});
</script>
when the HButton element click happened at the first I'm writing the object inside the "Common.currentTarget" and it saved successfully when I've watched variable but when another page loads completely and then trigger the event "_loadBackground" the value of "Common.currentTarget" have been lost, my question is how I can define a static variable like this to be permanent in whole of my pages?
You can set a cookie from javascript to store the data, and then access the cookie from another page. Cookies can persist just during the browser session, or you can give them an expiration. For HTML5, there is local storage.
All JavaScript data is unloaded when the page is changed or refreshed. There is no way around this in JavaScript itself. You will have to send data to the server instead. Probably the easiest way to do this is to store your data in a hidden field:
<input type="hidden" id="storable" />
....
document.getElementById("storable").value = // whatever value you want to store
Then on the server side you can transfer that data to the new page.
If you are redirecting client side, use a query parameter instead.
Related
i would like do a simple fireEvent("Refresh","")
from javascript outside of consumeEvent function.
as i want to be able to do a setinterval that would fireEvent "Refresh"
and put the event name inside a table 'do refresh query' in the web reporting
so eventually the table will refresh itself every 1 minute for example.
(i want to be able to refresh every table i have in the dashboard separately with different time interval)
the problem is that i'm able to do fireEvent only from the consumeEvent function
and then use context.fireEvent("Refresh","") but this can happen every time i have a different event occurring from the dashboard and it's not good enough
Event could be thrown anywhere with context's event manager instance:
<script type="text/javascript">
context.eventMgr().fireExternalEvent("eventName", eventValue)
</script>
Also you can fire events if you have access to ic3Reporting instance:
for example:
var ic3Application = ic3.startReport(options);
In that case you can fire app events in such way :
<script type="text/javascript">
//get ic3application instance
var ic3Application = ic3.startReport(options);
setInterval(function(){
ic3Application.fireEvent('table1-refresh', {})
},60000)
setInterval(function(){
ic3Application.fireEvent('table2-refresh', {})
},120000)
</script>
Then just set event names to "do Refresh Query" tables' event.
UPDATE
Version of script inside ic3report.html
<script type="text/javascript">
var ic3root = "../"
var ic3rootLocal = "../"
var options = {
root: ic3root,
rootLocal: ic3rootLocal,
callback: function () {
$('#intro').remove();
var options = {
<!-- ic3-start-report-options (DO NOT REMOVE - USED TO GENERATE FILES) -->
};
var ic3Application = ic3.startReport(options);
setInterval(function () {
ic3Application.fireEvent('ic3-table', {})
},20000)
};
ic3ready(options);
</script>
UPDATE
Here is a report with an example.
I'm injecting all my js code to front page, but it needs pictures for ui and stuff, that can be imported only with the help of chrome.extension.getUrl and can be called only from content-script, so I've found tons of advices how to pass data to content page, and nothing of about how pass data back, is it possible at all?
My code now looks like this:
my js code, that will be injected with other code:
var Content = {};
$(document).contentReady = function(content) {
Content = content;
$(document).ready(function () {/*cool stuff here, that require content*/});
}
var event = new CustomEvent('LoadContent');
window.dispatchEvent(event);
content-script:
document.querySelector('head').appendChild(jsCode);
window.addEventListener("LoadContent", function(evt) {
var content =
{
data: "url(" + chrome.extension.getURL('content.smth') + ")"
};
document.contentReady(content);
}, false);
And, obviously, I get document.contentReady is not a function
But declaring function in document was the only(!) advice of about how to pass data back from content-script after about 2 hours of googling.
Nothing stops you from making the CustomEvent-based communication bi-directional, and it can pass data with detail property:
// Page script
window.addEventListener('RecieveContent', function(evt) {
// do something cool with evt.detail
});
var event = new CustomEvent('LoadContent');
window.dispatchEvent(event);
// Content script
window.addEventListener('LoadContent', function(evt) {
content = /* ... */
var event = new CustomEvent('RecieveContent', {detail: content});
window.dispatchEvent(event);
});
A more in-depth answer can be found here.
However, you should ask yourself whether you even need the page-level script to query for data, since you fully control when it's injected. You can use uni-directional approach after you make sure the code has executed:
// Page script
window.addEventListener('RecieveContent', function(evt) {
// do something cool with evt.detail
});
// Content script
jsCode.onload = function() {
// This fires after the page script finishes executing
content = /* ... */
var event = new CustomEvent('RecieveContent', {detail: content});
window.dispatchEvent(event);
}
document.querySelector('head').appendChild(jsCode);
You can pass JS data to the page by creating a new script tag. For example:
function injectScript(code) {
var body = document.getElementsByTagName('body')[0];
var s = document.createElement('script');
s.innerHTML = code;
body.appendChild(s);
}
injectScript('var foo = 2;');
So for your particular example, you should be able to do:
injectScript('document.contentReady({data: url(' + blahblah + '})');
Not pretty (what is when you're working with overwriting content scripts?) but it works.
Content Scripts do not share window object with normal scripts on the page. Both of them work on different context.
In your case, you are registering an event listener on window and listening for the event on other context (window). Hence, your event listener will never be called.
However, there is one alternative approach I can see to communicate between content script and normal script is by using MutationObserver.
Idea
Define a node with some Id under which you will create subnodes corresponding to an event.
Register Mustation Observer in your script.
From content script, add the nodes with data as data-* api.
Implementation Example
Content Script
var submitEvent = function(category, action, label) {
var eventObserverPlaceholder = document.getElementById('events-observer-placeholder'),
$eventEl = $('<span></span>').attr({
'data-category': category,
'data-action': action,
'data-label': label
});
eventObserverPlaceholder.appendChild($eventEl.get(0));
};
Normal Script for registering Mutation Observer:
RQ.Methods.addObserverForEvents = function(targetNode) {
var observer = new MutationObserver(RQ.Methods.handleMutationList);
// Notify me when a new child is added
var observerConfig = {
attributes: false,
childList: true,
characterData: false
};
observer.observe(targetNode, observerConfig);
return observer;
};
RQ.mutationObserver = RQ.Methods.addObserverForEvents(document.getElementById('events-observer-placeholder'));
Links
https://davidwalsh.name/mutationobserver-api
https://developer.mozilla.org/en/docs/Web/API/MutationObserver
Working Example:
I have used the same approach in Requestly Chrome Extension for submitting events to Google Analytics.
Content Script: https://github.com/requestly/chrome-extension/blob/master/src/Shared/utils.js#L26
Normal Script: https://github.com/requestly/web/blob/gh-pages/js/scripts/tracker.js#L35
in the jquery.get() function, the first parameter is URL, is that the url to the content I want to retrieve or to the Controller/action method.
The problem is I'm building an asp.net-mvc application and I'm not sure what to pass as this parameter. Right now I'm passing my partialview.cshtml but nothing is being returned, not sure if I'm doing this right or wrong.
Here's what I got
<div id="editor_box"></div>
<button id="add_button">add</button>
<script>
var inputHtml = null;
var appendInput = function () {
$("#add_button").click(function() {
if (!inputHtml) {
$.get('AddItem.cshtml', function (data) {
inputHtml = data;
$('#editor_box').append(inputHtml);
});
} else {
$('#editor_box').append(inputHtml);
}
})
};
</script>
also, what is the second parameter "function (data)" is this the action method?
You need to remove var appendInput = function () { from the script. You are defining a function but never calling it. Just use the following (update you action and controller) names
<script>
var inputHtml = null;
$("#add_button").click(function() {
if (!inputHtml) {
$.get('#Url.Action("SomeAction", "SomeController")'', function (data) {
inputHtml = data;
$('#editor_box').append(inputHtml);
});
} else {
$('#editor_box').append(inputHtml);
}
});
</script>
Edit
Based on your script you appear to be requiring the content only once (you then cache it and add it again on subsequent clicks. Another alternative would be to render the contents initially inside a hidden <div> element, then in the script clone the contents of the <div> and append it to the DOM
<div id="add style="display:none">#Html.Partial("AddItem")</div>
$("#add_button").click(function() {
$('#editor_box').append($('add').clone());
});
The first argument to $.get is the URL which will respond with the expected data. jQuery/JavaScript don't care what kind of server side architecture you have or the scripting language. Whether the URL looks like a file AddItem.cshtml or a friendly route like /User/Sandeep, it doesn't matter as far as the client side is concerned.
In the case of ASP.NET, your URL endpoint can be generated like so:
$.get('#Url.Action("SomeAction", "SomeController")', function (data) {
I have a dijit tree that when a node is clicked it loads an html page in the center content page. One of the html pages is a login page and I'd like to check a cookie to see if they have already logged on, so I can set the page appropriately if the page gets re-loaded. Is there a way to check for a cookie on page load, or perhaps a better method than this? Thanks
my code for the tree is:
TOCSet: function (TOCStore) {
var myModel = new ObjectStoreModel({
store: TOCStore,
query: { root: true }
});
// Create the Tree.
var tree = new Tree({
model: myModel,
onClick: function (item, node, evt) {
// Get the URL from the item, and navigate to it
evt.preventDefault();
var href = item.url;
registry.byId('Content').set('href', href); //set the page on node clicks
}
});
tree.placeAt("TOC");
tree.startup();
ready(function () {
registry.byId("Content").set("href", "Login.htm");//set the login page at start
});
}
I set the cookie using "dojo/cookie" after successful login
function SetLoginCookie(lia) {
cookie("LoggedInAs", lia);
}
and then used "dojo/ready" to check for the cookie when the page reloads
ready(function () {
var lia = cookie("LoggedInAs");
alert(lia + " is logged in");
});
I am bit new to knockout and jquery mobile, There was a question which is already answered, I need to optimize the PageStateManager class to use generic bindings, currently PageStateManager can only use for one binding,I would really appreciate if someone can guide me to create a generic class to manage page states with knockout bindings Heere is the working code,http://jsfiddle.net/Hpyca/14/
PageStateManager = (function () {
var viewModel = {
selectedHospital: ko.observable()
};
var changePage = function (url, viewModel) {
console.log(">>>>>>>>" + viewModel.id());
$.mobile.changePage(url, {viewModel: viewModel});
};
var initPage = function(page, newViewModel) {
viewModel.selectedHospital(newViewModel);
};
var onPageChange = function (e, info) {
initPage(info.toPage, info.options.viewModel);
};
$(document).bind("pagechange", onPageChange);
ko.applyBindings(viewModel, document.getElementById('detailsView'));
return {
changePage: changePage,
initPage: initPage
};
})();
Html
<div data-role="page" data-theme="a" id="dashBoardPage" data-viewModel="dashBoardViewModel">
<button type="button" data-bind="click: goToList">DashBoard!</button>
</div>
New dashboard model
var dashBoardViewModel = function() {
var self = this;
self.userName = ko.observable('Welcome! ' + "UserName");
self.appOnline = ko.observable(true);
self.goToList = function(){
//I would like to use PageStateManager here
// PageStateManager.changePage($("#firstPage"),viewModel);
ko.applyBindings(viewModel,document.getElementById("firstPage"));//If I click Dashbord button multiple times it throws and multiple bind exception
$.mobile.changePage($("#firstPage"));
}
}
ko.applyBindings(dashBoardViewModel,document.getElementById("dashBoardPage"));
update url : http://jsfiddle.net/Hpyca/14/
Thank you in advance
I would probably go for creating a NavigationService which only handles changing the page and let knockout and my view models handle the state of the pages.
An simple example of such a NavigationService could be:
function NavigationService(){
var self = this;
self.navigateTo = function(pageId){
$.mobile.changePage($('#' + pageId));
};
}
You could then, in your view models just call it when you want it to navigate to a new page. One example would be upon selection of a hospital (which could be done either via a selection function or by manually subscribing to changes to the selectedHospital observable):
self.selectHospital = function(hospital){
self.selectedHospital(hospital);
navigationService.navigateTo('detailsView');
};
Other than the call to the navigationService to navigate, it's just ordinary knockout to keep track of which viewmodel should be bound where. A lot easier than having jquery mobile keeping track of which viewmodel goes where, if you ask me.
I have updated your jsfiddle to show a sample of how this could be done, making as few changes as possible to the HTML code. You can find the updated fiddle at http://jsfiddle.net/Hpyca/15/