Image cropper doesn't work within nested foreach - umbraco7

I have a problem in Umbraco 7. I'm using a nested Multiple Node Tree Picker, but the GetCropUrl doesn't work. The crop function is ok, I've already used it.
#{
if (CurrentPage.HasValue("artists"))
{
var artistList = CurrentPage.artists.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var artistCollection = Umbraco.Content(artistList);
foreach (var artist in artistCollection)
{
if (artist.HasValue("coverImages"))
{
var coverImagesList = artist.coverImages.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var coverImagesCollection = Umbraco.Media(coverImagesList);
foreach (var coverImage in coverImagesCollection.RandomOrder().Take(1).Where("Visible"))
{
<img src="#coverImage.GetCropUrl(305, 195)"/>
}
}
}
}
}
Update:
I changed the code and I started to use Id.
When I use this:
foreach (var coverImage in coverImagesCollection)
<p>#coverImage.Id</p>
<img src="#Umbraco.TypedMedia(1105).Url"/>
}
I got back the the image id from #coverImage.Id, and the image is working.
When I use this:
foreach (var coverImage in coverImagesCollection)
<img src="#Umbraco.TypedMedia(coverImage.Id).Url"/>
}
The image is still good.
After I'm cropping with fix id.
foreach (var coverImage in coverImagesCollection)
<img src="#Umbraco.TypedMedia(1105).GetCropUrl(305, 195)"/>
}
Working, but then:
foreach (var coverImage in coverImagesCollection)
<img src="#Umbraco.TypedMedia(coverImage.Id).GetCropUrl(305, 195)"/>
}
I got an error:
'Umbraco.Web.Models.PublishedContentBase' does not contain a definition for 'GetCropUrl'
How is that possible?

I've got an answer from Umbraco forum. He said coverImage.Id is dynamic, so I need to try this, and it worked perfectly:
foreach (var coverImage in coverImagesCollection)
<img src="#Umbraco.TypedMedia((int)coverImage.Id).GetCropUrl(305, 195)"/>
}

Related

Show custom Attribute with SCP for Configurable Product Magento

I want to add values from Custom Attribute to short description of Configurable Product in Magento. I am using SCP module to show dynamically short description, title and price for this one regarding to "Associated Simple Products ". The price, Title and short description work fine but it not change the long description and not show the custom Attributes associated to Simple product.
Can some body help me with this problem? I need some indication how can I do that?
I think that I can do it on the original file configurable.php from SCP (Simple Configurable products) module that I attached to this post but I am not sure.
Thank you in advance.
public function getJsonConfig()
{
$config = Zend_Json::decode(parent::getJsonConfig());
$childProducts = array();
//Create the extra price and tier price data/html we need.
foreach ($this->getAllowProducts() as $product) {
$productId = $product->getId();
$childProducts[$productId] = array(
"price" => $this->_registerJsPrice($this->_convertPrice($product->getPrice())),
"finalPrice" => $this->_registerJsPrice($this->_convertPrice($product->getFinalPrice()))
);
if (Mage::getStoreConfig('SCP_options/product_page/change_name')) {
$childProducts[$productId]["productName"] = $product->getName();
}
if (Mage::getStoreConfig('SCP_options/product_page/change_description')) {
$childProducts[$productId]["description"] = $product->getDescription();
}
if (Mage::getStoreConfig('SCP_options/product_page/change_short_description')) {
$childProducts[$productId]["shortDescription"] = $product->getShortDescription();
}
if (Mage::getStoreConfig('SCP_options/product_page/change_attributes')) {
$childBlock = $this->getLayout()->createBlock('catalog/product_view_attributes');
$childProducts[$productId]["productAttributes"] = $childBlock->setTemplate('catalog/product/view/attributes.phtml')
->setProduct($product)
->toHtml();
}
#if image changing is enabled..
if (Mage::getStoreConfig('SCP_options/product_page/change_image')) {
#but dont bother if fancy image changing is enabled
if (!Mage::getStoreConfig('SCP_options/product_page/change_image_fancy')) {
#If image is not placeholder...
if($product->getImage()!=='no_selection') {
$childProducts[$productId]["imageUrl"] = (string)Mage::helper('catalog/image')->init($product, 'image');
}
}
}
}
//Remove any existing option prices.
//Removing holes out of existing arrays is not nice,
//but it keeps the extension's code separate so if Varien's getJsonConfig
//is added to, things should still work.
if (is_array($config['attributes'])) {
foreach ($config['attributes'] as $attributeID => &$info) {
if (is_array($info['options'])) {
foreach ($info['options'] as &$option) {
unset($option['price']);
}
unset($option); //clear foreach var ref
}
}
unset($info); //clear foreach var ref
}
$p = $this->getProduct();
$config['childProducts'] = $childProducts;
if ($p->getMaxPossibleFinalPrice() != $p->getFinalPrice()) {
$config['priceFromLabel'] = $this->__('Price From:');
} else {
$config['priceFromLabel'] = $this->__('');
}
$config['ajaxBaseUrl'] = Mage::getUrl('oi/ajax/');
$config['productName'] = $this->getProduct()->getName();
$config['description'] = $this->getProduct()->getDescription();
$config['shortDescription'] = $this->getProduct()->getShortDescription();
if (Mage::getStoreConfig('SCP_options/product_page/change_image')) {
$config["imageUrl"] = (string)Mage::helper('catalog/image')->init($this->getProduct(), 'image');
}
$childBlock = $this->getLayout()->createBlock('catalog/product_view_attributes');
$config["productAttributes"] = $childBlock->setTemplate('catalog/product/view/attributes.phtml')
->setProduct($this->getProduct())
->toHtml();
if (Mage::getStoreConfig('SCP_options/product_page/change_image')) {
if (Mage::getStoreConfig('SCP_options/product_page/change_image_fancy')) {
$childBlock = $this->getLayout()->createBlock('catalog/product_view_media');
$config["imageZoomer"] = $childBlock->setTemplate('catalog/product/view/media.phtml')
->setProduct($this->getProduct())
->toHtml();
}
}
if (Mage::getStoreConfig('SCP_options/product_page/show_price_ranges_in_options')) {
$config['showPriceRangesInOptions'] = true;
$config['rangeToLabel'] = $this->__('to');
}
//Mage::log($config);
return Zend_Json::encode($config);
//parent getJsonConfig uses the following instead, but it seems to just break inline translate of this json?
//return Mage::helper('core')->jsonEncode($config);
}

htmlagilitypack remove row attributes

How do we remove the inline height attribute from html?
<tr style="height:2px;">
</tr>
<tr style="height:2px;">
</tr>
I want only height attributes to be removed from all tr tags.
Thanks a lot in advance,
You can:
If your trs have no other styles other than height, you can simply remove strip them from their style attribute (the line I commented out)
Otherwise, you can write something like the snippet below to filter which style keys you want to remove
string html = #"<tr style='height:2px;'>
</tr>
<tr style='height:2px;'>
</tr>";
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
var trs = doc.DocumentNode.SelectNodes("tr");
foreach (var tr in trs)
{
Console.WriteLine(tr.OuterHtml);
//tr.Attributes.Remove("style");
var filteredStyles = GetStyles(tr.GetAttributeValue("style"), "height");
tr.SetAttributeValue("style", string.Join(":", filteredStyles));
Console.WriteLine(tr.OuterHtml);
}
Helper function:
private static List<string> GetStyles(string style, params string[] keysToRemove)
{
List<string> styles = new List<string>();
var stylesKeyPairs = style.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
if (keysToRemove != null)
{
foreach (var styleKeyPair in stylesKeyPairs)
{
var styleKeys = styleKeyPair.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
if (!keysToRemove.Contains(styleKeys.FirstOrDefault()))
styles.Add(styleKeyPair);
}
}
else
styles.AddRange(stylesKeyPairs);
return styles;
}
Output (for both solutions, in this case):

Performance of Foreach and Template binding in knockout

Have been looking into the performance issues with the foreach and template binding. In our single page app, we have nested foreach/templates. Below is the jsperf url, which gives the information on a plain array rendered without a foreach and the one with foreach; where the test with title "Expanded loop markup" is better than the "Nested foreach" binding.
Also observed that the corrsponding "foreach via template" tests for nested and expanded are much more time consuming than the ones without foreach via template.
jsperf url:
http://jsperf.com/knockout-nested-foreach-vs-expanded-markup/2
Would appreciate your help on the performance with knockout 3.1.0
The performance issue is present with the knockout 3.2 version as well.
Want to know how to decrease the load time with nested foreach and/or template bindings.
In line with what Hans outlined, if you are really looking to squeeze the most performance out of the client-side. A custom binding working directly with the collection, building HTML as a string and injecting it using something like element.innerHTML.
A simple example below:
ko.bindingHandlers.innerHtml = {
init: function (element, valueAccessor) {
var lst = ko.unwrap(valueAccessor());
if (lst) {
var html = '';
for (var i = 0; i < lst.length; i++) {
html += '<li>' + lst[i] + '</li>';
}
if (html)
element.innerHTML = html;
}
}
};
var vm = function(){
var self = this;
self.lst = ko.observableArray();
for (var i = 0; i < 100; i++) {
var ary = [];
for (var j = 0; j < 1000; j++)
{
ary.push(j)
}
self.lst.push({ num: i, numAry: ary});
}
};
ko.applyBindings(new vm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: $data.lst">
<li>
<span data-bind="text: num"></span>
<ul data-bind="innerHtml: numAry"></ul>
</li>
</ul>

Extracting via HtmlAgilityPack

I'm using the HtmlAgilityPack and trying to extract an image name from html. Here's the html string I have:
sHtml = "<HTML><HEAD></HEAD><BODY>Here are some images.</br>1) < IMG style='MARGIN-BOTTOM: 20px; MARGIN-LEFT: 20px' align=right src='images/sample001.jpg'>2) < IMG style='MARGIN-BOTTOM: 25px; MARGIN-LEFT: 25px' align=right src='images/sample002.png'></br> And some docs as well.</br>1) href='javascript:parent.POPUP({url:'testDoc001.htm',type:'shared',width:600,height:645})'></br>2) href='javascript:parent.POPUP({url:'testDoc002.html',type:'shared',width:700,height:712})'></br></BODY></HTML>"
In WPF C# I pass this string into the following routine:
private static List<string> ExtractHtmlInfo(string sHtml)
{
HtmlDocument doc = new HtmlDocument();
doc.Load(new StringReader(sHtml));
HtmlNode root = doc.DocumentNode;
List<string> anchorTags = new List<string>();
//foreach (HtmlNode link in root.SelectNodes("//a"))
foreach (HtmlNode link in root.SelectNodes("//img"))
{
string att = link.OuterHtml;
anchorTags.Add(att);
}
return anchorTags;
}
When I step through the code I see that the line:
string att = link.OuterHtml;
provides the entire < img node ... which is more than I want.
I would like anchorTags to have just the folder and name of the file, as in:
[0] = images/sample001.jpg
[1] = images/sample002.png
So, I need something other than .OuterHtml but cannot find it.
Can anyone help?
You are looking for the values of the src attributes of the image elements:
foreach (HtmlNode img in root.SelectNodes("//img"))
{
string att = img.Attributes["src"].Value;
anchorTags.Add(att);
}

Replacing tags in HtmlAgility

I'm trying to replace all of my h1 tags with h2 tags and I'm using HtmlAgility pack.
I did this:
var headers = doc.DocumentNode.SelectNodes("//h1");
if (headers != null)
{
foreach (HtmlNode item in headers)
{
//item.Replace??
}
}
and i got stuck there. I've tried this:
var headers = doc.DocumentNode.SelectNodes("//h1");
if (headers != null)
{
foreach (HtmlNode item in headers)
{
HtmlNode newNode = new HtmlNode(HtmlNodeType.Element, doc, item.StreamPosition);
newNode.InnerHtml = item.InnerHtml;
// newNode suppose to set to h2
item.ParentNode.ReplaceChild(newNode, item);
}
}
problem there is that i have no idea how to create a new h2, get all the attributes etc.
i'm sure theres a simple way to do that, any ideas?
var headers = doc.DocumentNode.SelectNodes("//h1");
if (headers != null)
{
foreach (HtmlNode item in headers)
{
item.Name = "h2"
}
}
A similar approach replacing the tags using Descendants instead of SelectNodes:
IEnumerable<HtmlNode> tagDescendants = doc.DocumentNode.Descendants("h1");
foreach (HtmlNode htmlNode in tagDescendants)
{
htmlNode.Name = "h2";
}

Resources