Fancybox not working with Simple Configurable Products (SCP) - fancybox

I need some help with Javascript to get fancybox working with SCP. The following solution has not worked for me although I'm aware I'm missing some fundamental code. The first product image works perfectly opening the fancybox lightbox but once you select from the configurable dropdowns it changes the image which then does not call the lightbox and opens in the browser.
SCP advice is:
To fix, it's often just a matter of editing the showFullImageDiv function in the scp_product_extension.js file: Change evalScripts to true if it's not already, and possibly you'll also need to remove the code which exists in a few places which looks like: product_zoom = new Product.Zoom('image', 'track', 'handle', 'zoom_in', 'zoom_out', 'track_hint');
I tried this but it's not just a simple matter of removing "product_zoom..." my understanding is that fancybox needs to be called replace this line of code.
Original:
Product.Config.prototype.showFullImageDiv = function(productId, parentId) {
var imgUrl = this.config.ajaxBaseUrl + "image/?id=" + productId + '&pid=' + parentId;
var prodForm = $('product_addtocart_form');
var destElement = false;
var defaultZoomer = this.config.imageZoomer;
prodForm.select('div.product-img-box').each(function(el) {
destElement = el;
});
if(productId) {
new Ajax.Updater(destElement, imgUrl, {
method: 'get',
evalScripts: true,
onComplete: function() {
//Product.Zoom needs the *image* (not just the html source from the ajax)
//to have loaded before it works, hence image object and onload handler
if ($('image')){
var imgObj = new Image();
imgObj.src = $('image').src;
imgObj.onload = function() {product_zoom = new Product.Zoom('image', 'track', 'handle', 'zoom_in', 'zoom_out', 'track_hint'); };
} else {
destElement.innerHTML = defaultZoomer;
product_zoom = new Product.Zoom('image', 'track', 'handle', 'zoom_in', 'zoom_out', 'track_hint')
}
}
});
} else {
destElement.innerHTML = defaultZoomer;
product_zoom = new Product.Zoom('image', 'track', 'handle', 'zoom_in', 'zoom_out', 'track_hint');
}
};
I know I need to call fancybox in the below locations but not sure how to go about it. From what I understand fancybox is called on pageload so not sure imgObj.onload will even work?
Product.Config.prototype.showFullImageDiv = function(productId, parentId) {
var imgUrl = this.config.ajaxBaseUrl + "image/?id=" + productId + '&pid=' + parentId;
var prodForm = $('product_addtocart_form');
var destElement = false;
var defaultZoomer = this.config.imageZoomer;
prodForm.select('div.product-img-box').each(function(el) {
destElement = el;
});
if(productId) {
new Ajax.Updater(destElement, imgUrl, {
method: 'get',
evalScripts: true,
onComplete: function() {
//Product.Zoom needs the *image* (not just the html source from the ajax)
//to have loaded before it works, hence image object and onload handler
if ($('image')){
var imgObj = new Image();
imgObj.src = $('image').src;
imgObj.onload = CALL FANCYBOX
} else {
destElement.innerHTML = defaultZoomer;
CALL FANCYBOX
}
}
});
} else {
destElement.innerHTML = defaultZoomer;
CALL FANCYBOX
}
};
Unfortunately my javascript is very basic and any help on what I need to add would be gratefully received. I found a few posts with the same issue but no solution.
Thanks

Related

Can't update title in desktop version of word

I have an Office Addin and am trying to update the title of the document on desktop. i have tried 2 diffrent ways and none of them works on hte desktop. It works fine on word online but not on the desktop.
Word.run(async (context) => {
var newTitle = document.getElementById("inputTitle") as HTMLInputElement;
console.log(newTitle.value);
context.document.properties.title = newTitle.value;
});
This code works online but not on the desktop. I have also tried doing doing it in this way.
Office.context.document.customXmlParts.getByNamespaceAsync("http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
function (resultCore) {
var xmlPart = resultCore.value[0];
xmlPart.getNodesAsync('*/*', function (nodeResult) {
for (var i = 0; i < nodeResult.value.length; i++) {
var node = nodeResult.value[i];
console.log("BaseName: ")
console.log(node.baseName);
if (node.baseName === "title") {
var newTitle = document.getElementById("inputTitle") as HTMLInputElement;
console.log("title that you entered: " + newTitle.value);
console.log(node);
node.setNodeValueAsync(newTitle.value, { asyncContext: "StateNormal" }, function (data) { });
}
}
});
});
Does anyone know why it doesn't work or have some other solution to my problem?
The following code works for me, including on desktop. Note that you have to await the Word.run. Also, you have to load the title and then sync to make sure you have changed the title on the actual document and not merely in the proxy object in your task pane code.
await Word.run(async (context) => {
var newTitle = document.getElementById("inputTitle") as HTMLInputElement;
console.log(newTitle.value);
context.document.properties.title = newTitle.value;
const myProperties = context.document.properties.load("title");
await context.sync();
console.log(myProperties.title);
});

html2canvas - the screenshotted canvas is always empty/blank

I have a div that i want to screenshot and save,
here is my code
function _download(uri, filename)
{
var el = $('.sf-download-button');
if (el.length)
{
var link = document.createElement('a');
if (typeof link.download === 'string')
{
link.href = uri;
link.download = filename;
document.body.appendChild(link);
//simulate click // this causes page to download an empty html file not sure why
link.click();
//remove the link when done
document.body.removeChild(link);
}
else
{
window.open(uri);
}
}
}
function _save()
{
window.takeScreenShot = function ()
{
var a =document.getElementById("my-div");
html2canvas(document.getElementById("the-div-that-i-want-to-screenshot"), {
onrendered: function (canvas)
{
document.body.appendChild(canvas);
a.append(canvas);
},
width: 220,
height: 310
});
};
$("#btnSave2").click(function ()
{
html2canvas(document.getElementById("data"), {
onrendered: function (canvas)
{
_download_card(canvas.toDataURL(), 'save.png');
}
});
});
}
This is the code i got it from web and added some of my own stuff.code was working i believe but right now, when I click on the button show me the image, it creates the image i can see it but it is just blank.
I tried every possible code combination from jsfiddle and all that and couldn't get anything different as a result.
What could be going wrong here?
I solved the problem by simply changing the browser,
It was not working with Chrome but works perfectly on Mozilla.
Also i changed the code to this,
$("#btnSave").click(function() {
html2canvas($("#card"), {
onrendered: function(canvas) {
theCanvas = canvas;
document.body.appendChild(canvas);
// Convert and download as image
$("#img-out").append(canvas);
// Clean up
//document.body.removeChild(canvas);
}
});
});
Works perfect on Mozilla only.

Use Protractor browser.driver as a variable

I'm using page object model and I'm stuck at how to put the browser.driver elements as a variable.
Here is an example of using it with Protractor's element:
var Messages = function() {};
var messagesLink = element(by.css('a[href*="/Messages"]'));
Messages.prototype.visitPage = function() {
messagesLink.click();
};
exports.Messages = new Messages();
Then I can use Messages.visitPage(); throughout my test. The problem is when I try to do the same thing with browser.driver:
var Login = function() {};
var usernameField = browser.driver.findElement(by.id('UserName'));
var passwordField = browser.driver.findElement(by.id('Password'));
var signOnButton = browser.driver.findElement(by.css('input[value="Sign On"]'));
var registeredUserName = 'user';
var registeredUserPass = 'pass';
Login.prototype.loginAsRegisteredUser = function() {
loginAs(registeredUserName, registeredUserPass);
};
var loginAs = function(userName, pass) {
usernameField.sendKeys(userName);
passwordField.sendKeys(pass);
signOnButton.click();
};
exports.Login = new Login();
The test instantly fails before even starting, throwing this error NoSuchElementError: Unable to locate element: *[id="UserName"]. The reason why I'm using browser.driver is because I'm accessing elements on a non-angular page. I want to try and keep angular and non-angular references separate from each other.
I'm not sure how Protractor handles this but in Selenium I can use the variable like so, static By cancelButton = By.id("cphMain_btnCancel");.
So, is there anyway that this can be done using Protractor?
Spec File:
var home = require('../../pages/home/Home.js').Home;
var headerHome = require('../../pages/home/HeaderHome.js').HeaderHome;
var login = require('../../pages/Login.js').Login;
describe('Registered User | DEV_Smoke |--- Home page: ', function() {
it('Navigates to the Home page', function() {
home.visitPage();
});
it('Prints the current URL (see build.log)', function() {
home.verifyHomeUrl();
});
it('Clicks Sign On link and signs in as a registered user', function() {
headerHome.clickSignOnLink();
login.loginAsRegisteredUser();
});
});
Easiest way would be to just wrap the findElement in functions and call them as needed
var Login = function() {};
var usernameField = function() {
return browser.driver.findElement(by.id('UserName')); //returns promise
}
var passwordField = function() {
return browser.driver.findElement(by.id('Password'));
}
var signOnButton = function() {
return browser.driver.findElement(by.css('input[value="Sign On"]'));
}
var registeredUserName = 'user';
var registeredUserPass = 'pass';
Login.prototype.loginAsRegisteredUser = function() {
loginAs(registeredUserName, registeredUserPass);
};
var loginAs = function(userName, pass) {
usernameField().sendKeys(userName);
passwordField().sendKeys(pass);
signOnButton().click();
};
exports.Login = new Login();
browser.driver is of type Webdriver and when calling findElement, selenium-webdriver will try to evaluate wherever it is stated in your code. So prior to your login method and possibly navigation to the login page, you are automatically looking for the WebElements for UserName, Password, and input[value="SignOn"].
In your code snippet, it looks like you should use element. When using element, at runtime, the findElement will be evaluated. This allows for more reusable code.
For non-angular pages, you might have to provide your own syncing or some arbitrary sleep. This usually occurs with animations, long load screens, etc.
Also make sure you return your promises so the jasmine wrapper evaluates your function properly.
var usernameField = element(by.id('UserName'));
var passwordField = element(by.id('Password'));
var signOnButton = element(by.css('input[value="Sign On"]'));
// make sure you return your promises so the jasmine wrapper
// evaluates your function properly.
var loginAs = function(userName, pass) {
return usernameField.sendKeys(userName).then(() => {
return passwordField.sendKeys(pass).then(() => {
return signOnButton.click();
});
});
};

Was using .bind but now haved to use .delegate... have tried .undelegate?

Heres the jsfiddle, jsfiddle.net/kqreJ
So I was using .bind no problem for this function but then I loaded more updates to the page and found out that .bind doesn't work for content imported to the page but just for content already on the page! Great!
So I switched it up to .delegate which is pretty cool but now I can't figure out how to .bind .unbind my function the way it was???
Function using .bind which worked perfect... except didn't work on ajax content.. :(
$('.open').bind("mouseup",function(event) {
var $this = $(this), handler = arguments.callee;
$this.unbind('mouseup', handler);
var id = $(this).attr("id");
var create = 'nope';
var regex = /\d+$/,
statusId = $('#maindiv .open').toArray().map(function(e){
return parseInt(e.id.match(regex));
});
var divsToCreate = [ parseInt(id) ];
$.each(divsToCreate, function(i,e)
{
if ( $.inArray(e, statusId) == -1 ) {
create = 'yup';
}
});
if( create == 'yup' ) {
if(id) {
$.ajax({
type: "POST",
url: "../includes/open.php",
data: "post="+ id,
cache: false,
success: function(html) {
$('.open').html(html);
$this.click(handler);
}
});
}
}
});
New function using .delegate that is not binded and creates multiple instances?
$('#maindiv').delegate("span.open", "mouseup",function(event) {
var $this = $(this), handler = arguments.callee;
$this.unbind('mouseup', handler);
var id = $(this).attr("id");
var create = 'nope';
var regex = /\d+$/,
statusId = $('#maindiv .open').toArray().map(function(e){
return parseInt(e.id.match(regex));
});
var divsToCreate = [ parseInt(id) ];
$.each(divsToCreate, function(i,e)
{
if ( $.inArray(e, statusId) == -1 ) {
create = 'yup';
}
});
if( create == 'yup' ) {
if(id) {
$.ajax({
type: "POST",
url: "../includes/open.php",
data: "post="+ id,
cache: false,
success: function(html) {
$('.open').html(html);
$this.click(handler);
}
});
}
}
});
I've spent hours trying to figure this out because I like learning how to do it myself but I had to break down and ask for help... getting frustrated!
I also read that when your binding and unbinding .delegate you have to put it above the ajax content? I've tried using .die() and .undelegate()... Maybe I just don't know where to place it?
Take a look at undelegate
It does to delegate what unbind does to bind.
In your case, I think it'd be something like:
$('#maindiv').undelegate("span.open", "mouseup").delegate("span.open", "mouseup" ...
Then you can drop the $this.unbind('mouseup', handler); within the function.

how do i make a jquery plugin

I'm trying to make a jquery plugin
but it's not working what a'm i doing wrong
(function($){
$.fn.rss({
//pass the options variable to the function
rss: function(options) {
//Set the default values, use comma to separate the settings, example:
var defaults = {
feedUrl: ''
}
var options = $.extend(defaults, options);
return this.each(function() {
var Setting = options;
//code to be inserted here
$.ajax({
type: "GET",
url: Setting.feedUrl,
dataType: "xml",
success: function(xml) {
$(xml).find('channel').each(function(){
$(xml).find('image').each(function(){
var title2 = $(this).find('title').text();
var url2 = $(this).find('link').text();
$('<div class="title"></div>').html(''+title2+'').fadeIn(1000).appendTo('#title');
});
$(xml).find('item').each(function(){
var title = $(this).find('title').text();
var brief = $(this).find('description').text();
var url = $(this).find('link').text();
$('<div class="items"></div>').html('<div class="dis">'+brief+'</div>').fadeIn(1000).appendTo('#blab');
});
});
}
});
});
}
});
})(jQuery)
By writing $.fn.rss(...), you're calling a non-existent function.
You need to create a function by writing
$.fn.rss = function(...) { ... };