Custom Controls and Web Resources (scripts) - asp.net

I am developing a Server Custom Control (.NET), a "DatePicker" with the jQueryUI Plugin.
So, i have the next script, that is loaded as a webResource:
JavaScript
$(function () {
$("#" + ctrlInput).datepicker({
maxDate: MaxDate,
minDate: MinDate
});
});
As you can see, i have javascript variables, so, for loading the script and the variables, i do the next:
C#
string javascriptVariables = String.Format(
"var MinDate = '{0}'; var MaxDate = '{1}'; var ctrlInput = '{2}';",
MinDate ?? DateTime.MinValue.ToShortDateString(),
MaxDate ?? DateTime.MaxValue.ToShortDateString(),
_textBox.ClientID
);
// Load javascript variables (it will be load every time i add a control)
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "dateValues" + _textBox.ClientID, javascriptVariables, true);
// Load jQueryPlugin (it is loaded only once, and this is the problem)
Page.ClientScript.RegisterClientScriptResource(this.GetType(), "[[resourceName]]");
It works fine. The problem is when i add this control to a page more than once.
And it is because the script variables are loaded fine, but the RegisterClientScriptResource doesn't load the jQuery Plugin again! And i don't know how i can force the load! Because i can't set the resource key to the RegisterClientScriptResource
Does anybody know how to solve this?
Thanks

I don't think you're taking the problem the right way.
Using global variables (in js) especially when they're actually only used locally is a very bad idea. source
Loading jQuery or a jQuery plugin more than once can also be a source of bugs. source
What i would do is to think of another way of passing variables to your javascript, something like data attributes.
You're probably having an html input generated with from server control, add data attributes for your dates :
<input type="text" ... data-mindate="01/01/2013" data-maxdate="12/31/2013" />
Next step is, instead of feeding the global variables to the datepicker function, use the data attributes :
$('#whatever').data('mindate');
or
$('#whatever').attr('data-mindate');
And a fast demo : http://jsfiddle.net/JjemN/

Related

How can I tell if my Google content experiment is running?

I've created a google content experiment without redirects using the docs.
The basic implementation involves a javascript snippet that uses the following code to choose the version of the experiment:
<!-- Load the Content Experiment JavaScript API client for the experiment -->
<script src="//www.google-analytics.com/cx/api.js?experiment=YOUR_EXPERIMENT_ID"></script>
<script>
// Ask Google Analytics which variation to show the user.
var chosenVariation = cxApi.chooseVariation();
</script>
<!-- Load the JQuery library -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script>
// Define JavaScript for each page variation of this experiment.
var pageVariations = [
function() {}, // Original: Do nothing. This will render the default HTML.
function() { // Variation 1: Banner Image
document.getElementById('banner').src = 'bay-bridge.jpg';
},
function() { // Variation 2: Sub-heading Text
document.getElementById('heading').innerHTML = 'Look, a Bridge!';
},
function() { // Variation 3: Button Text
document.getElementById('button').innerHTML = 'Learn more';
},
function() { // Variation 4: Button Color
document.getElementById('button').className = 'button button-blue';
}
];
// Wait for the DOM to load, then execute the view for the chosen variation.
$(document).ready(
// Execute the chosen view
pageVariations[chosenVariation]
);
</script>
However, when I visit the page using an incognito window, I only see the first variation of the experiment. When I check chosenVariation in the console, it's always 0. In fact, when I call cxApi.chooseVariation(); in the console, it always returns 0.
Is this because google recognizes my incognito browser windows, or is something broken with cxApi.chooseVariation(); or in my implementation?
I had the same problem, 100% of the sessions were given the original (0) variation. In order to fix the problem, I added the javascript code provided by the experiment. Go to your experiment (edit), click Setting up your experiment code, manually insert the code, copy the code in there.
Now since you (and I) don't want to have a redirect, remove this part at the end of the code <script>utmx('url','A/B');</script>. If your page is templated, you can use a variable and insert your experiment key (not experiment id) where you see var k='########-#'
Now either very few people use the experiments in a client-only fashion or we're totally stupid because it would seem to me that the guide is wrong and there's absolutely no documentation that shows a working client-only setup.

Meteor - handling events in nested templates... without polluting 'Session' variable

I've come across this situation several times now and I realise I'm not really confident about the 'meteor/right' way to handle it.
Suppose I have a form with several parts - each represented by a template - and within each part there are more templates representing eg. datepickers etc.
<template name='myForm'>
{{>partOne}}
{{>partTwo}}
<button class='submit'>Submit</button>
</template>
<template name='partOne'>
{{>widget}}
{{>widget}}
</template>
<template name='widget'>
<input class='datepicker' />
</template>
I want to keep track of my form as the user fills it out - on the level of the 'myForm' template - but all the events are happening at the level of 'widget'.
One solution I keep seeing (e.g. in this SO answer) is to just put everything in the global Session variable. Like so
Template.widget.events({
'click .select' : function(event, template){
var name = template.data.name;
Session.set(name, $(event.currentTarget).val());
}
});
And then in myForm I should do something like this
Template.myForm.rendered = function(){
Tracker.autorun(function(){
var name = Session.get('name');
// do something
});
}
But as my forms are getting more complicated, I find this is really turning into a mess on the myForm template level, all while filling up my Session variable with data that isn't really application-global.
I'd be really grateful for any ideas on how others deal with this ! Keeping templates and widgets modular while still being able to follow and react to their triggered events from parent templates...
You're not alone in feeling like something just isn't right. This is one of the reasons there's a lot of talk about a Blaze 2. Here's what I do:
Create an app global namespace (e.g. G = {}). I usually use the first letter of the app name & do this in lib/config/_namespace.js
Put your collections in G.Collections or G.C,
Put your shared functions in G.Fx, etc...
Put your template vars in G.T.
Then, save that variable to G.T.varName. In doing so, you can use it in rendered as well as events and helpers. As a perk, it's super easy to find all your "globals" because they're all in the G object. Additionally, you can now 'use strict' again.
Then, to keep it clean:
Template.parentTemplate.destroyed = function() {
G.T = {};
};
So if you need reactivity, just make a ReactiveDict:
Template.parentTemplate.created = function() {
G.T.RD = new ReactiveDict();
};
You can use a file-level ReactiveVar or ReactiveDict, instead of the Session object.

Best way to retrieve image from server using ajax [duplicate]

Is it possible to reload an image with an identical file name from a server using jQuery?
For example, I have an image on a page, however, the physical image can change based on user actions. Note, this does not mean the file name changes, but the actual file itself.
ie:
User views image on default page
User uploads new image
Default image on page does not change(I assume this is due to the file name being identical, the browser uses the cached version)
Regardless of how often the code below is called, the same issue persists.
$("#myimg").attr("src", "/myimg.jpg");
In the jQuery documentation, the "load" function would be perfect if it had a default method of firing the event as opposed to binding a callback function to a successful/complete load of an element.
Any assistance is greatly appreciated.
It sounds like it's your browser caching the image (which I now notice you wrote in your question). You can force the browser to reload the image by passing an extra variable like so:
d = new Date();
$("#myimg").attr("src", "/myimg.jpg?"+d.getTime());
It's probably not the best way, but I've solved this problem in the past by simply appending a timestamp to the image URL using JavaScript:
$("#myimg").attr("src", "/myimg.jpg?timestamp=" + new Date().getTime());
Next time it loads, the timestamp is set to the current time and the URL is different, so the browser does a GET for the image instead of using the cached version.
This could be one of the two problems you mention yourself.
The server is caching the image
The jQuery does not fire or at least doesn't update the attribute
To be honest, I think it's number two. Would be a lot easier if we could see some more jQuery. But for a start, try remove the attribute first, and then set it again. Just to see if that helps:
$("#myimg").removeAttr("src").attr("src", "/myimg.jpg");
Even if this works, post some code since this is not optimal, imo :-)
with one line with no worries about hardcoding the image src into the javascript (thanks to jeerose for the ideas:
$("#myimg").attr("src", $("#myimg").attr("src")+"?timestamp=" + new Date().getTime());
To bypass caching and avoid adding infinite timestamps to the image url, strip the previous timestamp before adding a new one, this is how I've done it.
//refresh the image every 60seconds
var xyro_refresh_timer = setInterval(xyro_refresh_function, 60000);
function xyro_refresh_function(){
//refreshes an image with a .xyro_refresh class regardless of caching
//get the src attribute
source = jQuery(".xyro_refresh").attr("src");
//remove previously added timestamps
source = source.split("?", 1);//turns "image.jpg?timestamp=1234" into "image.jpg" avoiding infinitely adding new timestamps
//prep new src attribute by adding a timestamp
new_source = source + "?timestamp=" + new Date().getTime();
//alert(new_source); //you may want to alert that during developement to see if you're getting what you wanted
//set the new src attribute
jQuery(".xyro_refresh").attr("src", new_source);
}
This works great! however if you reload the src multiple times, the timestamp gets concatenated to the url too. I've modified the accepted answer to deal with that.
$('#image_reload_button').on('click', function () {
var img = $('#your_image_selector');
var src = img.attr('src');
var i = src.indexOf('?dummy=');
src = i != -1 ? src.substring(0, i) : src;
var d = new Date();
img.attr('src', src + '?dummy=' + d.getTime());
});
Have you tried resetting the image containers html. Of course if it's the browser that is caching then this wouldn't help.
function imageUploadComplete () {
$("#image_container").html("<img src='" + newImageUrl + "'>");
}
Some times actually solution like -
$("#Image").attr("src", $('#srcVal').val()+"&"+Math.floor(Math.random()*1000));
also not refresh src properly, try out this, it worked for me ->
$("#Image").attr("src", "dummy.jpg");
$("#Image").attr("src", $('#srcVal').val()+"&"+Math.floor(Math.random()*1000));
Using "#" as a delimiter might be useful
My images are kept in a "hidden" folder above "www" so that only logged users are allowed access to them. For this reason I cannot use the ordinary <img src=/somefolder/1023.jpg> but I send requests to the server like <img src=?1023> and it responds by sending back the image kept under name '1023'.
The application is used for image cropping, so after an ajax request to crop the image, it is changed as content on the server but keeps its original name. In order to see the result of the cropping, after the ajax request has been completed, the first image is removed from the DOM and a new image is inserted with the same name <img src=?1023>.
To avoid cashing I add to the request the "time" tag prepended with "#" so it becomes like <img src=?1023#1467294764124>. The server automatically filters out the hash part of the request and responds correctly by sending back my image kept as '1023'. Thus I always get the last version of the image without much server-side decoding.
Based on #kasper Taeymans' answer.
If u simply need reload image (not replace it's src with smth new), try:
$(function() {
var img = $('#img');
var refreshImg = function(img) {
// the core of answer is 2 lines below
var dummy = '?dummy=';
img.attr('src', img.attr('src').split(dummy)[0] + dummy + (new Date()).getTime());
// remove call on production
updateImgVisualizer();
};
// for display current img url in input
// for sandbox only!
var updateImgVisualizer = function() {
$('#img-url').val(img.attr('src'));
};
// bind img reload on btn click
$('.img-reloader').click(function() {
refreshImg(img);
});
// remove call on production
updateImgVisualizer();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<img id="img" src="http://dummyimage.com/628x150/">
<p>
<label>
Current url of img:
<input id="img-url" type="text" readonly style="width:500px">
</label>
</p>
<p>
<button class="img-reloader">Refresh</button>
</p>
I may have to reload the image source several times. I found a solution with Lodash that works well for me:
$("#myimg").attr('src', _.split($("#myimg").attr('src'), '?', 1)[0] + '?t=' + _.now());
An existing timestamp will be truncated and replaced with a new one.
If you need a refresh of the exact URL and your browser has the image cached, you can use AJAX and a request header to force your browser to download a new copy (even if it isn't stale yet). Here's how you'd do that:
var img = $("#myimg");
var url = img.attr("src");
$.ajax({
url: url,
headers: { "Cache-Control": "no-cache" }
}).done(function(){
// Refresh is complete, assign the image again
img.attr("src", url);
});
Nothing else worked for me because while appending a token to the query string would download the new image, it didn't invalidate the image in the cache at the old URL so future requests would continue to show the old image. The old URL is the only one sent to the browser, and the server was directing the client to cache the image for longer than it should.
If this still doesn't refresh the image for you, see if this answer helps. For more information, here is documentation on the Cache-Control request header.
In the html:
foreach (var item in images) {
<Img src="#Url.Content(item.ImageUrl+"?"+DateTime.Now)" >
}
I simply do this in html:
<script>
$(document).load(function () {
d = new Date();
$('#<%= imgpreview.ClientID %>').attr('src','');
});
</script>
And reload the image in code behind like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
image.Src = "/image.jpg"; //url caming from database
}
}

javascript contents are not getting loaded,if i create a tab/contentPane dymaically with .xhtml as input

I am creating a dynamic tab/contentPane as below in home.xhtml file and i am trying to call a function display which is present in order.xhtml,its not getting called. what ever java script is there in order.xhtml is not getting loaded.
In home.xhtml
if(dijit.byId('ordersummary')!=null){
dijit.byId('ordersummary').destroy();
}
newTab= new dijit.layout.ContentPane({
id : 'ordersummary',
title : 'Order Summary',
href : 'order.xhtml',
closable : true
});
dijit.byId('tabContainer').addChild(newTab);
dijit.byId('tabContainer').selectChild(dijit.byId("ordersummary"));
javascript in order.xhtml
<script type="text/javascript">
//<![CDATA[
function display(){
alert(" I M BEING CALLED");
}
</script>
There are two ways about this, either a make the script type dojo/method.
Or use the extended dojox/layout/ContentPane.
http://livedocs.dojotoolkit.org/dijit/layout/ContentPane#executing-javascript-inside-contentpane
While I'm not familiar with the dojo toolkit, I think you should put the JavaScript function in the main file or load the JavaScript dynamically like;
How do I include a JavaScript file in another JavaScript file?
dijit.layout.ContentPane will not support javascript,i mean it will not execute the javascript content in the input file.
dojox.layout.ContentPane is advanced one and it will support javascript.

jquery script removal

I need to remove the following script from my page(ASP.NET 3.5), leaving all other scripts intact:
<script type="text/javascript">
//<![CDATA[
alert('Save Sucessful.');
</script>
Should be something like $('html').children('script').remove(':contains("alert")) but this exact syntax doesn't work.
Rather than a pop-up alert, why not provide feedback with a page element (in the DOM)?
It would be there still rather than be there again.
Okay, if you cannot change it you could replace the windows.alert function, if it's executed before the code in question (usually in DOM order).
BTW, you can't just test the string (my first thought) since "Successful" should have two 'c's and the owner of that code might fix it.
But you could mute all alerts for the first 10 seconds with:
var _alert = window.alert, _alertStart=new Date().getTime();
window.alert = function() {
var delay = (new Date().getTime()) - _alertStart;
if (delay > 10000)
_alert.apply( window, arguments );
};
Or, if you want to delete every inline script that contains "alert" you could use:
$('script:contains("alert")').remove();
Note that that pattern matches the script tag in which it occurs, so you could change it if it matters:
$('script:contains("al'+'ert")').remove();
$('html').children('script:contains("alert")').remove();

Resources