I have upgraded a solution from MVC 3 to MVC 4.
I have 2 specific JavaScript functions that does not work anymore after upgrade.
Tabs
This is how the tabs now render
I suspect it has to do with the JavaScript version with the new framework? I am not sure.
Code:
<script type="text/javascript">
$(function () {
$("#tabs").tabs();
$('.taberize').each(function () {
var e = $(this);
var panels = e.parents('.ui-tabs-panel');
if (panels.length == 0) { return; }
var tabId = $(panels[0]).attr('id');
e.attr('href', e.attr('href') + '#' + tabId);
});
$(".container").each(function (e) {
var height = $(document).height() - 230;
$(this).height(height);
});
});
2. On Row Hover function
The On-Row-Hover function does not work anymore, I have a "Action Menu" on the left side of my WebGrid, and on row hover, it display functions like Edit and Details menu... this is done in JavaScript.
<script type="text/javascript">
var prevRow = null;
$('#gridData table tbody tr').not(':first').hover(function()
{
$('#myMenu').hide();
if (prevRow != this)
{
if (prevRow != null)
{
$(prevRow).css("background","");
$('.actionButtons', $(prevRow)).hide();
}
$(this).css("background","#EDEFFF");
$('.actionButtons', $(this)).show();
prevRow = this;
}
},
function()
{
if (!$('#myMenu').is(":visible"))
{
if (prevRow != null)
{
$(prevRow).css("background","");
$('.actionButtons', $(prevRow)).hide();
prevRow = null;
}
}
});
$(".openmenu").contextMenu({ menu: 'myMenu', leftButton: true },
function(action, el, pos) {
contextMenuWork(action, el.parents('tr')[0].id , pos);
});
function contextMenuWork(action, id) {
switch (action) {
case "insert":
{
if($.browser.msie&&$.browser.version.substr(0,1)<8){var url='#Url.Action("Create", "Account")';document.location=url}else{CreateNewAccount()}
break;
}
case "createtask":
{
var url = '#Url.Action("CreateFromAccount", "UserTask")' + '/' + id;
document.location = url;
break;
}
case "linkassessment":
{
var url = '#Url.Action("CreateFromAccount", "Questionnaire")' + '/' + id;
document.location = url;
break;
}
case "details":
{
var url = '#Url.Action("Details", "Account")' + '/' + id;
document.location = url;
break;
}
case "edit":
{
var url = '#Url.Action("Edit", "Account")' + '/' + id;
document.location = url;
break;
}
case "createperson":
{
if($.browser.msie&&$.browser.version.substr(0,1)<8){var url='#Url.Action("Create", "Person")';document.location=url}else{CreateNewPerson(id)}
break;
}
case "createopportunity":
{
var url = '#Url.Action("Create", "Opportunity")' + '/' + id;
document.location = url;
break;
}
}
}
});
</script>
<div id="gridData">
<ul id="myMenu" class="contextMenu" style="display: none">
<li class="insert">Create New</li>
<li class="detail">Details</li>
<li class="edit">Edit</li>
</ul>
</div>
<table>
<tr>
<th class="field-actions-account" style="width: 75px">
Actions
</th>
<tr id="#Html.Encode(item.AccountID)">
<td>
<div class="actionButtons" style="display:none">
<img src="#Html.Raw(#Url.Content("~/Content/img/document-pencil-icon.png"))" alt="Edit" title="Edit" style="border:none"/>
<img src="#Html.Raw(#Url.Content("~/Content/img/testDetailsIcon.gif"))" alt="Details" title="Details" style="border:none" />
<img src="#Html.Raw(#Url.Content("~/Content/img/options.gif"))" alt="More Options" class="openmenu" title="More Options"/>
</div>
put your javascript code in section like this:
#section Head
{
<script type="text/javascript">
$(function () {
$("#tabs").tabs();
$('.taberize').each(function () {
var e = $(this);
var panels = e.parents('.ui-tabs-panel');
if (panels.length == 0) { return; }
var tabId = $(panels[0]).attr('id');
e.attr('href', e.attr('href') + '#' + tabId);
});
$(".container").each(function (e) {
var height = $(document).height() - 230;
$(this).height(height);
});
});
</script>
}
then be sure your "#RenderSection("Head", false) is under your #Scripts.Render("~/bundles/jquery") in your layout like this :
#Scripts.Render("~/bundles/jquery")
#RenderSection("Head", false)
and finally check your BundleConfig class has a code like this file :
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
}
The problem was, somehow the jquery.validate file has been modified, and that was causing my problem.
Related
I'm trying to create a simple images slider. The problem I'm facing is that the next and prev buttons only work the first time. Then when you hover an item again it doesn't work. When you hover an item the third time it works, and so on.
I just can't find what's causing this behaviour.
Here's a working fiddle
$('.item.with-sec-image').on('mouseenter', function() {
var $this = $(this);
/* load data only once */
if (!$this.hasClass('images-initialized')) {
var url = $this.data('handle').replace('.html', '.ajax');
var purl = $this.data('handle');
$.getJSON(url, function(data) {
if (data.images.length > 1) {
var slider = $this.find('.slider');
if (data.images.length >= 2 && data.images.length != slider.find('li.selected').length) {
$.each(data.images, function(index, image) {
var img_url = image.replace('50x50x2', '400x400x2')
if (slider.find('li.selected').data('index') != index) {
var $newImage = $('<li><img src="' + img_url + '" /></li>')
slider.append($newImage);
}
});
}
}
}).done(function() {
$this.addClass('images-initialized');
});
}
$this.on('click', '.slider-btn', function() {
updateSlider($this)
});
});
The function to update the slider
function updateSlider(navigation) {
var $this = navigation
var sliderContainer = $this.find('.images .slider'),
activeSlider = sliderContainer.children('.selected').removeClass('selected');
if ($this.hasClass('next')) {
(!activeSlider.is(':last-child')) ? activeSlider.next().addClass('selected'): sliderContainer.children('li').eq(0).addClass('selected');
} else {
(!activeSlider.is(':first-child')) ? activeSlider.prev().addClass('selected'): sliderContainer.children('li').last().addClass('selected');
}
}
And, this is my HTML:
<div class="item with-sec-image" data-handle="some-url">
<div class="images">
<ul class="slider">
<li data-index="0" class="selected"><img src="link-to-image" /></li>
</ul>
<ul class="slider-navigation">
<li class="prev btn-round slider-btn small"><i class="icon-left"></i></li>
<li class="next btn-round slider-btn small"><i class="icon-right"></i></li>
</ul>
</div>
</div>
$('.item.with-sec-image').on('mouseenter', function() {
var $this = $(this);
/* load data only once */
if (!$this.hasClass('images-initialized')) {
var url = $this.data('handle').replace('.html', '.ajax');
var purl = $this.data('handle');
$.getJSON(url, function(data) {
if (data.images.length > 1) {
var slider = $this.find('.slider');
if (data.images.length >= 2 && data.images.length != slider.find('li.selected').length) {
$.each(data.images, function(index, image) {
var img_url = image.replace('50x50x2', '400x400x2')
if (slider.find('li.selected').data('index') != index) {
var $newImage = $('<li><img src="' + img_url + '" /></li>')
slider.append($newImage);
}
});
}
}
}).done(function() {
$this.addClass('images-initialized');
});
}
$this.on('click', '.slider-btn', function() {
updateSlider($this)
});
});
// The function to update the slider
function updateSlider(navigation) {
var $this = navigation
var sliderContainer = $this.find('.images .slider'),
activeSlider = sliderContainer.children('.selected').removeClass('selected');
if ($this.hasClass('next')) {
(!activeSlider.is(':last-child')) ? activeSlider.next().addClass('selected'): sliderContainer.children('li').eq(0).addClass('selected');
} else {
(!activeSlider.is(':first-child')) ? activeSlider.prev().addClass('selected'): sliderContainer.children('li').last().addClass('selected');
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item with-sec-image" data-handle="some-url">
<div class="images">
<ul class="slider">
<li data-index="0" class="selected"><img src="link-to-image" /></li>
</ul>
<ul class="slider-navigation">
<li class="prev btn-round slider-btn small"><i class="icon-left"></i></li>
<li class="next btn-round slider-btn small"><i class="icon-right"></i></li>
</ul>
</div>
</div>
Ok i figured out the problem.
your are binding the click event on mouseenter which mean that it will be bind many time. so one click will equal multiple clicks and that why you are encountering this behavior.
I have made small changes to your code look below. and also here is fiddler working example
function updateSlider(btn) {
var $this = btn.closest(".item.with-sec-image");
var sliderContainer = $this.find('.images .slider'),
activeSlider = sliderContainer.children('.selected').removeClass('selected');
if (btn.hasClass('next')) {
(!activeSlider.is(':last-child')) ? activeSlider.next().addClass('selected'): sliderContainer.children('li').eq(0).addClass('selected');
} else {
(!activeSlider.is(':first-child')) ? activeSlider.prev().addClass('selected'): sliderContainer.children('li').last().addClass('selected');
}
}
// second image only on hover
$(function(){
$('.item.with-sec-image').on('mouseenter', function() {
var $this = $(this);
if (!$this.hasClass('images-initialized')) {
var url = $this.data('handle').replace('.html', '.ajax');
var purl = $this.data('handle');
$.getJSON(url, function(data) {
if (data.images.length > 1) {
var slider = $this.find('.slider');
if (data.images.length >= 2 && data.images.length != slider.find('li.selected').length) {
$.each(data.images, function(index, image) {
var img_url = image.replace('50x50x2', '400x400x2')
if (slider.find('li.selected').data('index') != index) {
var $newImage = $('<li><img src="' + img_url + '" /></li>')
slider.append($newImage);
}
});
}
}
}).done(function() {
$this.addClass('images-initialized');
});
}
}).on('click', '.slider-btn', function() {// this should be run outside the mouseenter function or else it will bind many times
updateSlider($(this))
});
});
Background:
Page B is dynamically loaded in Page A by XMLHttpRequest. Page B contains list of name which on swipe reloads Page B itself.
Issue:
When Page A is loaded swipe is working fine, but when Page B reloads, Swipe functionality fails to function.
Tried with swipe.js in Page B as well but nothing seems to work.
Would be great help if anyone could point out issue... Thanks
Code
Page A:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<script>
var d = '<?php echo $result["d_delayed"]; ?>';
var q = '<?php echo $result["d_queued"]; ?>';
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("detect_change");
source.onmessage = function(event) {
var obj = JSON.parse(event.data);
// Reload on Queue Update
document.getElementById("title_change").innerHTML = obj.name;
if(d != obj.delay || q != obj.queue){
loadDoc("");
}
};
}
</script>
<div>
<p id="demo"></p>
</div>
<script>
//Load through XMLHttpRequest
function loadDoc(search) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "swipe_page.php", true);
xhttp.send();
}
loadDoc(search);
</script>
</body>
</html>
Page B (swipe_page.php)
<ul class="list-group list-group-flush patient-list swipe-list bottom-pad-ul">
<li class="list-group-item">
<div class="patient-list__info swipe swipe-left-right" linkRight="#link" linkLeft="#link">
<a data-toggle="modal" class="bg-hov" data-target="#myModal"><span class="span-left-arrow"><i class="fa fa-chevron-left float-left" aria-hidden="true"></i></span></a>
<span class="patient-list__patient-name">User Name</span>
<a data-toggle="modal" data-target="#myModal"><span class="badge badge-light badge-pill patient-list__patient-badge patient-list__patient-badge--first">number</span></a>
</div>
<div class="patient-list__info patient-list__info--mirror" style="">
<i class="fa fa-reply" aria-hidden="true"></i>  Undo
</div>
</li>
</ul>
Swipe script
var s1 = Swiped.init({
query: 'li>.swipe-right',
list: false,
left: 5,
right: 0
});
var s2 = Swiped.init({
query: 'li>.swipe-left-right',
list: false,
left: 5,
right: 5
});
jQuery(document).on('touchstart', 'li>.swipe-right', function() {
s1.open;
});
jQuery(document).on('touchstart', 'li>.swipe-left-right', function() {
s2.open;
});
var onOpenfunction = function() {
var clickUndo = false;
var dir = this.dir;
var offset, invert_offser;
//jQuery(this.elem).css('transform', 'translate3d(0px, 0px, 0px)');
if (dir === 1) {
offset = '110%';
invert_offser = '-110%';
} else {
offset = '-110%';
invert_offser = '110%';
}
jQuery(this.elem).animate({left: offset});
console.log(offset);
jQuery('.patient-list__info--mirror',jQuery(this.elem).parent()).css('left',invert_offser).animate({left: 0});
jQuery('.patient-list__info--mirror',jQuery(this.elem).parent()).click(function () {
jQuery('.patient-list__info',jQuery(this).parent()).not('.patient-list__info--mirror').animate({left: 0});
jQuery(this).animate({left: invert_offser});
clickUndo = true;
jQuery(this).off();
});
var currentElem = this.elem;
var parentElem = jQuery(this.elem).parent();
setTimeout(function() {
if(!clickUndo) {
jQuery(parentElem).hide();
if(dir === 1){
console.log(jQuery(currentElem).attr('linkRight'));
var right_swipe = jQuery(currentElem).attr('linkRight');
$.ajax({url: right_swipe, success: function(result){
}});
} else {
console.log(jQuery(currentElem).attr('linkLeft'));
var left_swipe = jQuery(currentElem).attr('linkLeft');
$.ajax({url: left_swipe, success: function(result){
}});
}
}
}, 5000);
};
Swiped.init({
query: 'ul.swipe-list>li>.swipe-left-right',
onOpen: onOpenfunction
});
Swiped.init({
query: 'ul.swipe-list>li>.swipe-right',
onOpen: onOpenfunction
});
Finally I have figured out the underlying issue. As Page B is loaded by Ajax each time, Swipe script is not loaded.
All you have to do is load the swipe script each time when Page B is loaded.
Hope this helps save time for someone!!!
First and foremost I'd like to thank everyone who participates contributes and adds to the forums / community, you guys provide an extremely appreciated and valued resource to those that just need information and assistance when needed. Simple thing to do for some, but to many it means volumes. So thanks again.
I'm no coding or script expert but I definitely learn quick and know enough to get around and translate (especially if the language is explained) attempting to get a player on my site to populate and propagate a playlist based on an uploaded file string.
So far I have the player completely up and running, it properly parses the upload links to display the separate mp3 files to play as well as the separate description information per file.
The problem is when I click the play button all of the files mp3 play at once. I'm almost positive I need to add a forEach statement or something along those lines either here:
$(function(){
$('#player1').plp({
'volume': 80,
'playlist':[
{"title":"{$pic.video_descr }",
"author":"{.Me}",
"cover":"files/covers/fullfilename",
"mfile":"{.siteurl}{.fullfilename}",
"duration":"330"},
]
});
});
for each title, author, cover, duration and mfile,
or somewhere around here
function init_track(i){
cpl = i;
$this.find('.playlist span').removeClass('active');
$this.find('.playlist span:eq('+i+')').addClass('active');
$audio.src = options.playlist[i].mfile;
$this.find('.title').html(options.playlist[i].title);
$this.find('.author').html(options.playlist[i].author);
$this.find('.cover').attr('src', options.playlist[i].cover);
}
for(i=0; i < options.playlist.length; i++){
$this.find('.playlist').append('<span>'+options.playlist[i].author+' - '+options.playlist[i].title+'</span>');
}
init_track(cpl);
$this.find('.playlist span').click(function(){
init_track($(this).index());
});
here is the full .js
(function($) {
jQuery.fn.plp = function(options) {
var options = $.extend({
volume: 50,
playlist: [],
autostart: false
}, options);
var make = function() {
var $this = $(this);
var cpl = 0;
var $audio = new Audio();
var isrand = false;
$this.find('.volume').slider({
animate: true,
range: 'min',
value: options.volume,
min: 0,
max: 1,
step: 0.01,
slide: function(event, ui) {
$audio.volume = ui.value;
}
});
$this.find('.long').slider({
animate: true,
range: 'min',
value: 0,
min: 0,
max: 60,
step: 1,
slide: function(event, ui) {
$audio.currentTime = ui.value;
}
});
$audio.addEventListener('canplay', function(_event) {
if ($audio.duration) {
$this.find('.all').html(' / ' + toMinit($audio.duration));
$this.find('.long').slider({
'max': $audio.duration
});
} else {
this.find('.all').html(' / ' + toMinit(options.playlist[cpl].duration));
$this.find('.long').slider({
'max': options.playlist[cpl].duration
});
}
if (options.autostart) {
$audio.play();
$this.find('.tlb_stop').addClass('isplay');
} else {
options.autostart = true;
}
});
$audio.addEventListener('ended', function() {
if (isrand) {
var rand = cpl;
while (rand == cpl) {
rand = Math.floor(Math.random((options.playlist.length)));
}
init_track(rand);
} else {
if (cpl == options.playlist.length - 1) {
cpl = -1;
}
init_track(cpl + 1);
}
});
$audio.addEventListener('timeupdate', function() {
$this.find('.long').slider({
'value': $audio.currentTime
});
$this.find('.current').html(toMinit($audio.currentTime));
});
function toMinit(val) {
val = Number(val);
var ost = Math.floor(val % 60);
var tm = Math.floor(val / 60);
if (ost < 10) {
ost = '0' + ost;
}
if (tm < 10) {
tm = '0' + tm;
}
return tm + ':' + ost;
}
function init_track(i) {
cpl = i;
$this.find('.playlist span').removeClass('active');
$this.find('.playlist span:eq(' + i + ')').addClass('active');
$audio.src = options.playlist[i].mfile;
$this.find('.title').html(options.playlist[i].title);
$this.find('.author').html(options.playlist[i].author);
$this.find('.cover').attr('src', options.playlist[i].cover);
}
for (i = 0; i < options.playlist.length; i++) {
$this.find('.playlist').append('<span>' + options.playlist[i].author + ' - ' + options.playlist[i].title + ' < /span>');
}
init_track(cpl);
$this.find('.playlist span').click(function() {
init_track($(this).index());
});
$this.find('.tlb_prev').click(function() {
if (isrand) {
var rand = cpl;
while (rand == cpl) {
rand = Math.floor(Math.random() *
(options.playlist.length));
}
init_track(rand);
} else {
if (cpl === 0) {
cpl = options.playlist.length;
}
init_track(cpl - 1);
}
return false;
});
$this.find('.tlb_stop').click(function() {
if ($audio.paused) {
$audio.play();
$(this).addClass('isplay');
} else {
$audio.pause();
$(this).removeClass('isplay');
}
return false;
});
$this.find('.tlb_next').click(function() {
if (isrand) {
var rand = cpl;
while (rand == cpl) {
rand = Math.floor(Math.random() *
(options.playlist.length));
}
init_track(rand);
} else {
if (cpl == options.playlist.length - 1) {
cpl = -1;
}
init_track(cpl + 1);
}
return false;
});
$this.find('.vol_icon').click(function() {
$(this).toggleClass('active');
$this.find('.volume').fadeToggle(100);
return false;
});
$this.find('.pl_icon').click(function() {
$(this).toggleClass('active');
$this.find('.playlist').fadeToggle(100);
return false;
});
$this.find('.while_icon').click(function() {
if ($audio.loop) {
$(this).removeClass('active');
$audio.loop = false;
} else {
$(this).addClass('active');
$audio.loop = true;
}
return false;
});
$this.find('.rand').click(function() {
if (isrand) {
$(this).removeClass('active');
isrand = false;
} else {
$(this).addClass('active');
isrand = true;
}
return false;
});
};
return this.each(make);
};
})(jQuery);
Here is the PHP/HTML (smarty template):
<script type="text/javascript" src="/jquery.js">
</script>
<script type="text/javascript" src="/player.js">
</script>
{foreach item=pic from=$pics} {/foreach}
<table>
<tr>
<td valign="middle">
{if $pic.ext == 'yt'}
<div style=
"background-image:url('http://img.youtube.com/vi/{$pic.ytref}/0.jpg');">
<div style="height:120px; max-width:120px;">
<a alt="video no {$pic.videono}" href=
"http://www.youtube.com/v/{$pic.ytref}&fs=1&rel=0::"
title="Click to Play"><img height="120" onmouseout=
"this.src='playbtred.png'" onmouseover=
"this.src='playbty.png'" src="playbtred.png" width=
"120"></a>
</div>
</div>
<div style=
"width:60%;word-wrap: break-word;padding-bottom:20px;">
{$pic.video_descr }
</div>{elseif $pic.ext == 'mp3'}
<script type="text/javascript">
$(function(){
$('#player1').plp({
'volume': 80,
'playlist':[
{"title":"{$pic.video_descr }",
"author":"Test2",
"cover":"files/covers/1.jpg",
"mfile":"{$config.siteurl}{$pic.fullfilename}",
"duration":"330"},
]
});
});
</script><br>
<div style=
"width:60%;word-wrap: break-word;padding-bottom:20px;">
</div>{else} {include file='otheruploads.tpl'}<br>
{$pic.video_descr } {/if}
</td>
</tr>
</table>
<div class="player" id="player1">
<img alt="" class="cover" src=""><!--album cover-->
<span class="title"></span><!--song title-->
<span class="author"></span><!--artist-->
<div class="long"></div>
<div class="current">
00:00
</div>
<div class="all"></div>
<div class="volume"></div>
<div class="vol_icon"></div>
<div class="rand"></div>
<div class="while_icon"></div>
<div class="toolbar">
<div class="tlb_prev"></div>
<div class="tlb_stop"></div>
<div class="tlb_next"></div>
</div>
<div class="pl_icon active"></div>
<div class="playlist flexcroll"></div>
</div>{/if}
I'm just not sure where or how. I've literally spent the last two days searching and researching to figure it out. I'm so sure its simple, but I'm lost at the moment, and would GREATLY appreciate the help.
My code currently allows any link clicked under citations to open a new page. I'm trying to exclude the "More..." links from performing this function since these are used to add more links to the current page. Is there a way to do this?
Here's the jsfiddle
Here's my javascript
$(document).ready(function ($) {
var url = 'https://www.sciencebase.gov/catalog/item/504216b6e4b04b508bfd333b?
format=jsonp&fields=relationships,title,body,contacts';
$.ajax({
type: 'GET',
url: url,
jsonpCallback: 'getSBJSON',
contentType: "application/json",
dataType: 'jsonp',
success: function (json) {
var citeCount = 0;
var piCount = 0;
$('#project').append('<li><b>' + json.title + ' - </b>' + json.body + '</li>');
$('#project a').on('click', function (e) {
e.preventDefault();
if (citeCount == 1) {
return;
}
$.ajax({
type: 'GET',
url: 'https://www.sciencebase.gov/catalog/itemLink
/504216b6e4b04b508bfd333b?format=jsonp',
jsonpCallback: 'getSBJSON',
contentType: "application/json",
dataType: 'jsonp',
success: function (json) {
// Loop function for each section (10 citations per section)
var loopSection = function (start, stop) {
// Http setup for all links
var linkBase = "http://www.sciencebase.gov/catalog/item/";
// Link for citation information
var link = "";
for (var j = start; j < stop; j++) {
// Create a link using the realtedItemId
link = linkBase + json[j].relatedItemId;
// Title links
var $anchor = $("<a>", {
href: link,
id: "id" + j,
text: json[j].title
});
// .parent() will get the <li> that was just created and append to
//the first citation element
$anchor.appendTo("<li>").parent().appendTo("#citations");
}
}
var itemCount = json.length;
var numSections = Math.floor((itemCount / 10));
var moreLinks = $('More...');
var loopCount = 1;
loopSection(0, 10);
$('#citations').append(moreLinks);
$(moreLinks).on('click', function (e) {
e.preventDefault();
if (numSections > 1) {
loopSection((loopCount * 10), ((loopCount + 1) * 10));
$('#citations').append(moreLinks);
numSections -= 1;
loopCount++;
} else if (numSections <= 1) {
$("#nextLink").closest('a').remove();
loopSection((loopCount * 10), json.length);
}
});
},
error: function (e) {
console.log(e.message);
}
}); // END Second .ajax call
$('#project').on('click', function (e) {
e.preventDefault();
if (piCount == 1) {
return;
}
for (var i = 1; i < json.contacts.length; i++) {
$('#piHeading').append('<ul>' + "Name: " + json.contacts[i].name + ', ' + "Email: " + json.contacts[i].email + ', ' + "Phone: " + json.contacts[i].phone + '</ul>');
}
piCount++;
});
citeCount++;
}); // END Project link click event
$('#citations').on('click', function (e) {
e.preventDefault();
window.open('CitationsInfo.html', '_self');
});
},
error: function (e) {
console.log(e.message);
}
}); // END First .ajax call
}); // END Doc.ready
and Here's my html,
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="MainPage4.js"></script>
<script src="Citations.js"></script>
</head>
<body>
<h2>Project</h2>
<div class='wrapper'>
<ul id='project'></ul>
</div>
<h3>Citations</h3>
<div class='wrapper'>
<ul id='citations'></ul>
</div>
<h3>Principal Investigators</h3>
<div class='wrapper'>
<ul id='piHeading'></ul>
</div>
</body>
</html>
Thanks for the help
If you change the part of your code that is handling the global click event for the #citations container to include logic to filter out clicks where the target is the #nextLink, it should do what you want.
$('#citations').on('click', function (e) {
e.preventDefault();
if (!$(e.target).is($('#nextLink'))) {
window.open('CitationsInfo.html', '_self');
}
});
Removing the above section entirely also allow the "More..." link to work correctly, while still maintaining functionality on the individual links. The citations click event is masking the other behaviors.
jsfiddle
(Explanation at the bottom)
Helpful: Lines in code that have a (*) at start and end are the lines that i get a break on.
Hey guys i have a serious issue with a custom dojo widget.
I have the following code (services.aspx):
<asp:Content ID="Content2" ContentPlaceHolderID="formdojoRequirementsPlaceHolder"
runat="Server">
<script type="text/javascript">
dojo.require("js.Forms.ServiceDetails");
dojo.require("js.Forms.PendingServices");
dojo.require("js.Forms.CertificatesList");
dojo.addOnLoad(function() {
//LOCALIZATION
var glb_connections = [];
var ServiceDetailsTab = dijit.byId('ServiceDetails');
var PendingTaskTab = dijit.byId('PendingTask');
var PendingServicesTab = dijit.byId('PendingServices');
var CertificatesListTab = dijit.byId('CertificatesList');
var MessagesTab = dijit.byId('Messages');
if (ServiceDetailsTab) { ServiceDetailsTab.attr('title', glb_nlsStrings.ServiceTab) };
if (PendingTaskTab) { PendingTaskTab.attr('title', glb_nlsStrings.PendingTaskTab) };
if (PendingServicesTab) { PendingServicesTab.attr('title', glb_nlsStrings.PendingServicesTab) };
if (CertificatesListTab) { CertificatesListTab.attr('title', glb_nlsStrings.CertificatesTab) };
if (MessagesTab) { MessagesTab.attr('title', glb_nlsStrings.MessagesTab) };
ServiceDetailsTab = null;
PendingTaskTab = null;
PendingServicesTab = null;
CertificatesListTab = null;
MessagesTab = null;
//
var queryObj = Utils.General.GetQueryStringObject(window.location.href);
var organizationId = queryObj[Utils.General.Constants.queryParameters.ORGANIZATIONID];
var serviceTypeCode = queryObj[Utils.General.Constants.queryParameters.SERVICETYPECODE];
var tab = queryObj['glb_currentTab'];
if (dojo.byId("ServiceDetailsWdj") != undefined) {
*djtServiceDetails.serviceTypeCode = serviceTypeCode;*
glb_connections.push(dojo.connect(djtPendingServices, "onServiceInstanceDeleted", function() {
*djtServiceDetails.onBack();*
}));
*glb_connections.push(dojo.connect(djtServiceDetails, "onServiceCompleted", function() {
djtPendingServices._FindIncompleteServices(serviceTypeCode, glb_site_userID, organizationId);
}));*
}
else {
removeTab("ServiceDetails")
}
if (dojo.byId("PendingTaskWdj") != undefined) {
glb_subscriptions.push(dojo.subscribe("_serviceInstanceDeleted", function(child) {
*djtPendingServices._FindIncompleteServices(serviceTypeCode, glb_site_userID, organizationId);*
}));
glb_connections.push(dojo.connect(djtPendingServices, "onServiceInstanceCompleted", function() {
djtPendingServices._FindIncompleteServices(serviceTypeCode, glb_site_userID, organizationId);
if (dojo.byId("ServiceDetailsWdj") != undefined) { *djtServiceDetails.postCreate();* }
}));
djtPendingServices._FindIncompleteServices(serviceTypeCode, glb_site_userID, organizationId);
}
else {
removeTab("PendingTask")
}
removeTab("dataToBeSubmittedTab");
if (tab != undefined) {
glb_currentTab = tab;
var tabContainerWidget = dijit.byId('tabContainer');
tabContainerWidget.selectChild(glb_currentTab);
} else {
glb_currentTab = 'ServiceDetails';
}
glb_subscriptions.push(dojo.subscribe("tabContainer-selectChild", function(child) {
glb_currentTab = child.id;
}));
});
function removeTab(tabId) {
var tabContainerDijit = dijit.byId("tabContainer");
if (tabContainerDijit) {
var dataToBeSubmittedTabDijit = dijit.byId(tabId);
if (dataToBeSubmittedTabDijit) {
tabContainerDijit.removeChild(dataToBeSubmittedTabDijit);
}
}
}
dojo.addOnUnload(function() {
if (typeof glb_connections != "undefined")
dojo.forEach(glb_connections, dojo.disconnect);
if (typeof glb_subscriptions != "undefined")
dojo.forEach(glb_subscriptions, dojo.unsubscribe);
});
</script>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="formMainContentPlaceHolder" runat="Server">
<div id="ServiceDetails" dojotype="dijit.layout.ContentPane" title="Services" style="height: 95%">
<div id="divServiceDetails" runat="server">
<div dojotype="js.Forms.ServiceDetails" jsid="djtServiceDetails" id="ServiceDetailsWdj">
</div>
</div>
</div>
<div id="PendingTask" dojotype="dijit.layout.ContentPane" title="Pending Tasks" style="height: 95%">
<div id="divPendingTask" runat="server">
<div dojotype="js.Forms.PendingServices" jsid="djtPendingServices" id="PendingTaskWdj">
</div>
</div>
</div>
<div id="CertificatesList" dojotype="dijit.layout.ContentPane" title="Certificates"
style="height: 95%">
<div id="divCertificatesList" runat="server">
<div dojotype="js.Forms.CertificatesList">
</div>
</div>
</div>
</asp:Content>
The 3 files : 1.dojo.require("js.Forms.ServiceDetails");
2.dojo.require("js.Forms.PendingServices");
3.dojo.require("js.Forms.CertificatesList");
are the widgets.
The widget is build based on MVC.
The important thing here is the view part that the problem occurs so the code of the View follows:
dojo.provide("js.Forms.Views.ServiceDetailsView");
dojo.require("js.Forms.Controllers.ServiceDetailsController");
dojo.require("js.FormSteps.FormsList");
dojo.require("js.FormSteps.IncompleteServices");
dojo.require("BL.DataContracts.Entities.FormDefinition");
dojo.require("BL.DataContracts.Entities.ServiceFormInstance");
dojo.require("dijit._Widget");
dojo.require("dojox.dtl._DomTemplated");
dojo.require("dijit.form.Button");
dojo.require("dijit.TooltipDialog");
dojo.require("dijit.form.DropDownButton");
dojo.require("dijit.form.DateTextBox");
dojo.declare("js.Forms.Views.ServiceDetailsView", [dijit._Widget, dojox.dtl._DomTemplated], {
connections: null,
controller: null,
widgetsInTemplate: true,
templatePath: dojo.moduleUrl("js.Forms", "Templates/ServicesList.html"),
servicesList: null,
serviceTypeCode: null,
servicesDefinitions: null,
inCompleteServices: null,
isDissolved: null,
constructor: function() {
this.controller = new js.Forms.Controllers.ServiceDetailsController(this);
this.nlsStrings = dojo.i18n.getLocalization("Resources", "Resources");
var queryObj = Utils.General.GetQueryStringObject(window.location.href);
this.isDissolved = queryObj[Utils.General.Constants.queryParameters.ISDISSOLVED];
},
**postCreate: function(args, frag) {
this.inherited("postCreate", arguments);
this.ConnectEvents();
dojo.style(this.divBackButton, "display", "none");
if ((this.isDissolved == 'false') || (this.isDissolved == undefined)) {
this.FindServicesDefinitions();
this.SetButtonLabels();
}
},**
SetButtonLabels: function() {
this.btnBackService.attr('label', this.nlsStrings.btnBack);
},
ConnectEvents: function() {
this.connect(this.djtIncompleteServices, 'onCreateNewService', function() {
this.showFormDefinitions();
});
this.connect(this.djtIncompleteServices, 'onIncompleteServiceLoad', function(serviceinstanceid, isReturned) {
this.djtFormsList.isReturnedService = isReturned;
this.onFilterDefinitions(serviceinstanceid);
});
this.connect(this.djtIncompleteServices, 'onIncompleteServiceDeleted', function(serviceinstanceid) {
this.onDeleteServiceInstance(serviceinstanceid);
});
this.connect(this.djtFormsList, 'onServiceCompleted', function() {
this._ServiceCompleted();
});
},
DeleteIncompleteServiceFromModel: function(serviceinstanceid) {
this.controller.model.incompleteServicesList = dojo.filter(this.controller.model.incompleteServicesList, function(serviceinstance) { return serviceinstance.serviceinstanceid != serviceinstanceid; });
this.showIncompleteServices(this.controller.model.incompleteServicesList);
dojo.publish("_serviceInstanceDeleted");
},
onDeleteServiceInstance: function(serviceinstanceid) {
this.controller.DeleteServiceInstance(serviceinstanceid);
},
FindServicesDefinitions: function() {
this.controller.FindServices();
},
BindServicesList: function(servicesList) {
this.servicesList = servicesList;
this.buildRendering();
this.ShowServicesList(this.serviceTypeCode);
},
ShowServicesList: function(serviceTypeCode) {
//debugger;
dojo.style(this.divServices, "display", "block");
if (serviceTypeCode == Utils.General.Constants.serviceTypeCode.REGISTRATIONOFORGANIZATION) {
if (glb_currentRegistrationService) {
dojo.style(this.divServices, "display", "none");
this.controller.FindIncompleteRegistrationServices();
}
}
this.servicesListHeading.innerHTML = (serviceTypeCode == Utils.General.Constants.serviceTypeCode.CHANGEOFORGANIZATION) ?
this.nlsStrings.colOrganizationChangeServices : this.nlsStrings.colOrganizationChangeServices;
},
BindIncompleteRegistrationServices: function() {
//debugger;
dojo.style(this.divServices, "display", "block");
var incompleteRegistrationServices = this.controller.GetIncompleteRegistrationServices();
var hasIncompleteRegistrationServices = (incompleteRegistrationServices != null && incompleteRegistrationServices.length > 0);
dojo.query("a[servicecode]").forEach(function(node) {
//debugger;
if (hasIncompleteRegistrationServices) {
var idx = -1;
var nodeServiceCode = dojo.attr(node, "servicecode");
var incompleteRegServices = dojo.filter(incompleteRegistrationServices, function(item) {
return item.serviceCode == nodeServiceCode;
});
if (incompleteRegServices.length == 0) {
dojo.attr(node, "disabled", "disabled");
}
else {
for (var i = 0; i < incompleteRegistrationServices.length; i++) {
if (incompleteRegistrationServices[i].serviceCode == nodeServiceCode)
idx = i;
}
if (idx >= 0) {
if (incompleteRegistrationServices[idx].shouldEnable == false)
dojo.attr(node, "disabled", "disabled");
else
node.removeAttribute("disabled");
}
}
}
else {
//There are no incomplete regisistrations for the organization name.Disable any subservices.
if (dojo.attr(node, "servicecode") != glb_currentRegistrationService) {
dojo.attr(node, "disabled", "disabled");
}
}
});
},
onselectService: function(event) {
var domNode = event.srcElement;
if (!dojo.hasAttr(domNode, 'disabled')) {
var serviceCode = dojo.attr(domNode, "serviceCode");
this.servicesDefinitions = dojo.filter(this.servicesList.OrganizationServices, function(serviceDefinition) { return serviceDefinition.ServiceDefinitionID == serviceCode; });
if (Utils.General.GetQueryStringObject(window.location.href).organizationid == undefined) {
this.inCompleteServices = this.controller.FindIncompleteServices(serviceCode, 0);
}
else {
this.inCompleteServices = this.controller.FindIncompleteServices(serviceCode, Utils.General.GetQueryStringObject(window.location.href).organizationid);
}
}
},
onFilterDefinitions: function(serviceinstanceid) {
glb_serviceInstanceID = serviceinstanceid;
var filteredDefitions = this.controller.FilterFormsDefinitions(serviceinstanceid);
},
DeleteServiceDefinitionFromClient: function(serviceinstanceid) {
},
showFilteredFormDefinitions: function() {
//debugger;
var iscomplete = true;
var modl = this.controller.model.incompleteServiceFormsList;
var servDefinitions = dojo.clone(this.servicesDefinitions[0]);
var formsDef = servDefinitions.FormsDefinitions;
var formCode = null;
if (servDefinitions.IsVariableFee) {
var registrationForm = dojo.filter(modl, function(item) {
return item.formnumber == 'XI00Z';
});
if (registrationForm.length > 0) {
servDefinitions.Fee = registrationForm[0].CalculatedVariableFee;
}
}
for (var i = 0; i < formsDef.length; i++) {
formCode = formsDef[i].FormDefinitionID;
for (var j = 0; j < modl.length; j++) {
if (modl[j].formnumber == formCode) {
//Attach some dynamic properties to the form definitions
formsDef[i].pendingtaskid = modl[j].pendingtaskid;
formsDef[i].iscomplete = modl[j].iscomplete;
formsDef[i].drcorstatus = modl[j].drcorstatus;
if ((!modl[j].isDocument) && (modl[j].Attachments.length > 0)) {
formsDef[i].DocumentGuid = modl[j].Attachments[0].DocumentID;
}
if (modl[j].iscomplete == 0) {
iscomplete = false;
}
}
}
}
this.djtFormsList.IsCompleted(iscomplete);
this.djtFormsList.SetServiceFormsDefinitions(servDefinitions);
for (var i = 0; i < modl.length; i++) {
if (modl[i].isDocument) {
//Set the attachments for each document in the incomplete service form list
this.djtFormsList.SetDocumentAttachments(modl[i].formnumber, modl[i].Attachments);
}
}
dojo.style(this.divBackButton, "display", "block");
dojo.style(this.divServices, "display", "none");
dojo.style(this.divServiceFormsDefinitions, "display", "block");
dojo.style(this.divIncompleteServices, "display", "none");
},
showIncompleteServices: function(inCompleteServices) {
this.djtIncompleteServices.SetIncompleteServicesList(inCompleteServices);
dojo.style(this.divBackButton, "display", "block");
dojo.style(this.divServices, "display", "none");
dojo.style(this.divIncompleteServices, "display", "block");
},
showFormDefinitions: function() {
this.djtFormsList.IsCompleted(false);
glb_serviceInstanceID = 0;
this.djtFormsList.SetServiceFormsDefinitions(this.servicesDefinitions[0]);
this.djtFormsList.ClearDocumentAttachments();
dojo.style(this.divBackButton, "display", "block");
dojo.style(this.divServices, "display", "none");
dojo.style(this.divServiceFormsDefinitions, "display", "block");
dojo.style(this.divIncompleteServices, "display", "none");
},
onBack: function() {
dojo.style(this.divBackButton, "display", "none");
dojo.style(this.divServices, "display", "block");
dojo.style(this.divServiceFormsDefinitions, "display", "none");
dojo.style(this.divIncompleteServices, "display", "none");
this.buildRendering();
this.ShowServicesList(this.serviceTypeCode);
},
_ServiceCompleted: function() {
glb_serviceInstanceID = 0;
dojo.style(this.divBackButton, "display", "none");
dojo.style(this.divServices, "display", "block");
dojo.style(this.divServiceFormsDefinitions, "display", "none");
dojo.style(this.divIncompleteServices, "display", "none");
this.buildRendering();
this.ShowServicesList(this.serviceTypeCode);
this.onServiceCompleted();
},
onServiceCompleted: function() {
}
});
Ok so now let me explain the problem.
When i run this application under internet explorer 8 or 7 everything works perfectly.
But when i try to open it using IE9, Firefox or Chrome i get an error stating that "djtServiceDetails is not defined".
As i understood from debugging this is because when the file is executed the postCreate part of the View is not executed (a debugger in the postCreate is never found)
I have a similar page using the same structure as the above that works in all browsers and we could not locate any differences.
I hope that you might be able to tell me something that will help me solve this issue.
If you need any more information please let me know.
Thank you in advance
Solon
I have a suggestion that may or may not work. I tried reproducing your issue with simplified code and could not. As a rule, I do not provide a constructor function in my custom widgets. The code you have in the constructor can go in postMixInProperties.
Try changing your constructor function to the following:
postMixInProperties: function() {
this.inherited(arguments);
this.controller = new js.Forms.Controllers.ServiceDetailsController(this);
this.nlsStrings = dojo.i18n.getLocalization("Resources", "Resources");
var queryObj = Utils.General.GetQueryStringObject(window.location.href);
this.isDissolved = queryObj
[Utils.General.Constants.queryParameters.ISDISSOLVED];
},
I wonder if the dojo.i18n call, which will more than likely make an xhr request, causes the behavior you are seeing.
I believe its a problem with the parsing of your markup.. Thats basically the biggest caveat, using dojo since DOCTYPE and rendering engines are the hardest parts to 'guard' against in platform independant JS. I havent used < 1.7 for a while now but im fairly certain that the proper markup would be closer to this, using camelCase syntax on the custom attributes:
<div id="ServiceDetails" dojoType="dijit.layout.ContentPane" title="Services" style="height: 95%">
<div id="divServiceDetails" runat="server">
<div dojoType="js.Forms.ServiceDetails" jsId="djtServiceDetails" id="ServiceDetailsWdj">
</div>
</div>
</div>
<div id="PendingTask" dojoType="dijit.layout.ContentPane" title="Pending Tasks" style="height: 95%">
<div id="divPendingTask" runat="server">
<div dojoType="js.Forms.PendingServices" jsId="djtPendingServices" id="PendingTaskWdj">
</div>
</div>
</div>
<div id="CertificatesList" dojoType="dijit.layout.ContentPane" title="Certificates"
style="height: 95%">
<div id="divCertificatesList" runat="server">
<div dojoType="js.Forms.CertificatesList">
</div>
</div>
</div>
It will look messy either way through a validator =)
Again, with 1.6 im not sure but i think you could replace into html5 compat attribute naming schema, so that dojoType becomes data-dojo-type and jsIdwould be data-dojo-jsId (should look into these in reference api). In regards to jsId - you would be best off with referencing widgets through the dijit registry - the global scope exposure is on its way out in future versions. So instead of getting said object through /*window.*/ djtServiceDetails, call dijit.byId('djtServiceDetails')
Try it out, and with that said - i personally would also compile stuff like 'title', 'id', 'valueAttr' etc into the dojoProps attribute, so that:
<div dojoType="dijit.layout.ContentPane" jsId="registryKeyId" title="Dia Title" href="index101.html"></div>
becomes
<div dojoType="dijit.layout.ContentPane" dojoProps="id:'registryKeyId', title:'Dia Title', href:'index101.html'"></div>